da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include "sfhdr.h"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_PACKAGE_ast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifndef FIONREAD
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _sys_ioctl
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <sys/ioctl.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Read/Peek a record from an unseekable device
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin**
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin** Written by Kiem-Phong Vo.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define STREAM_PEEK 001
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SOCKET_PEEK 002
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __STD_C
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinssize_t sfpkrd(int fd, Void_t* argbuf, size_t n, int rc, long tm, int action)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinssize_t sfpkrd(fd, argbuf, n, rc, tm, action)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint fd; /* file descriptor */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinVoid_t* argbuf; /* buffer to read data */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinsize_t n; /* buffer size */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint rc; /* record character */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinlong tm; /* time-out */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint action; /* >0: peeking, if rc>=0, get action records,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin <0: no peeking, if rc>=0, get -action records,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin =0: no peeking, if rc>=0, must get a single record
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg ssize_t r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg int ntry, t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin reg char *buf = (char*)argbuf, *endbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rc < 0 && tm < 0 && action <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return sysreadf(fd,buf,n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = (action > 0 || rc >= 0) ? (STREAM_PEEK|SOCKET_PEEK) : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_stream_peek
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t &= ~STREAM_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if !_socket_peek
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t &= ~SOCKET_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(ntry = 0; ntry < 2; ++ntry)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _stream_peek
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((t&STREAM_PEEK) && (ntry == 1 || tm < 0) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct strpeek pbuf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.flags = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.ctlbuf.maxlen = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.ctlbuf.len = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.ctlbuf.buf = NIL(char*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.databuf.maxlen = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.databuf.buf = buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin pbuf.databuf.len = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = ioctl(fd,I_PEEK,&pbuf)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t &= ~STREAM_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { t &= ~SOCKET_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r > 0 && (r = pbuf.databuf.len) <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(action <= 0) /* read past eof */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = sysreadf(fd,buf,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(r > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /* stream_peek */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(ntry == 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* poll or select to see if data is present. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(tm >= 0 || action > 0 ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* block until there is data before peeking again */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ((t&STREAM_PEEK) && rc >= 0) ||
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* let select be interrupted instead of recv which autoresumes */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (t&SOCKET_PEEK) )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { r = -2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_poll
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r == -2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct pollfd po;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin po.fd = fd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin po.events = POLLIN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin po.revents = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = SFPOLL(&po,1,tm)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(errno == EAGAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { errno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = (po.revents&POLLIN) ? 1 : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_lib_poll*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _lib_select
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r == -2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _hpux_threads && vt_threaded
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define fd_set int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin fd_set rd;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct timeval tmb, *tmp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FD_ZERO(&rd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin FD_SET(fd,&rd);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(tm < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tmp = NIL(struct timeval*);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { tmp = &tmb;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tmb.tv_sec = tm/SECOND;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tmb.tv_usec = (tm%SECOND)*SECOND;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = select(fd+1,&rd,NIL(fd_set*),NIL(fd_set*),tmp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(errno == EAGAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { errno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = FD_ISSET(fd,&rd) ? 1 : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif /*_lib_select*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r == -2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#if !_lib_poll && !_lib_select /* both poll and select can't be used */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#ifdef FIONREAD /* quick and dirty check for availability */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin long nsec = tm < 0 ? 0 : (tm+999)/1000;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while(nsec > 0 && r < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { long avail = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((r = ioctl(fd,FIONREAD,&avail)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(errno == EAGAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { errno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* ioctl failed completely */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { r = -2;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = avail <= 0 ? -1 : (ssize_t)avail;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r < 0 && nsec-- > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sleep(1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r > 0) /* there is data now */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(action <= 0 && rc < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return sysreadf(fd,buf,n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(tm >= 0) /* timeout exceeded */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if _socket_peek
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(t&SOCKET_PEEK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#if __MACH__ && __APPLE__
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * work around macos 10.4 recv(MSG_PEEK) bug that consumes pipe() data
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin struct stat st;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static int recv_peek_ok;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!recv_peek_ok)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int fds[2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char tst[2];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tst[0] = 'a';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tst[1] = 'z';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin recv_peek_ok = (!pipe(fds) && write(fds[1], tst, 2) && recv(fds[0], tst, 1, MSG_PEEK) == 1 && tst[0] == 'a' && recv(fds[0], tst, 1, MSG_PEEK) == 1 && tst[0] == 'a') ? 1 : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(fds[0]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin close(fds[1]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (recv_peek_ok < 0 && !fstat(fd, &st) && !S_ISSOCK(st.st_mode))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t &= ~SOCKET_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while((r = recv(fd,(char*)buf,n,MSG_PEEK)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(errno == EINTR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if(errno == EAGAIN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { errno = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t &= ~SOCKET_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { t &= ~STREAM_PEEK;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* read past eof */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(action <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = sysreadf(fd,buf,1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#endif
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(r < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { if(tm >= 0 || action > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* get here means: tm < 0 && action <= 0 && rc >= 0 */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { /* number of records read at a time */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((action = action ? -action : 1) > (int)n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin action = n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while((t = sysreadf(fd,buf,action)) > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { r += t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(endbuf = buf+t; buf < endbuf;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*buf++ == rc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin action -= 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(action == 0 || (int)(n-r) < action)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r == 0 ? t : r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* successful peek, find the record end */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(rc >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin { reg char* sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = action == 0 ? 1 : action < 0 ? -action : action;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for(endbuf = (sp = buf)+r; sp < endbuf; )
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(*sp++ == rc)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if((t -= 1) == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = sp - buf;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* advance */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if(action <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin r = sysreadf(fd,buf,r);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return r;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}