home *** CD-ROM | disk | FTP | other *** search
- /* $Id: etherreadv.c,v 2.1 89/10/23 15:42:42 dupuy Exp $ */
-
- #include <sys/types.h> /* iovec (caddr_t) */
- #include <sys/uio.h> /* iovec */
-
- #include <errno.h> /* EWOULDBLOCK/EMSGSIZE */
-
- extern int errno;
-
- #include "libether.h"
-
- #ifdef __GNUC__
- #define alloca __builtin_alloca
- #else
- #ifdef lint
- extern double *dalloca ();
- #define alloca dalloca
- #else
- #ifdef sparc
- #include <alloca.h>
- #endif
- extern char *alloca ();
- #endif
- #endif
-
- #define HEADER 0
- #define USER 1
- #define WASTE (count - 1)
-
- /*
- * Reads and returns a single packet, filling in all fields. Reads on the
- * ethernet packet filter device always return one packet. Streams must be in
- * RMSGD mode for reads to return one packet at a time
- */
-
- int
- ether_readv (fd, packet)
- int fd;
- ether_vec *packet;
- {
- char waste[ETHER_MAX];
- int count = 2 + packet->iovcnt;
- struct iovec *iov =
- (struct iovec *) alloca (sizeof (struct iovec) * count);
-
- iov[HEADER].iov_len = ETHER_PKT;
- iov[HEADER].iov_base = (char *) packet;
-
- (void) bcopy ((char *) packet->iov, (char *) &iov[USER],
- (int) packet->iovcnt * sizeof (struct iovec));
-
- iov[WASTE].iov_len = sizeof (waste);
- iov[WASTE].iov_base = waste;
-
- if ((count = readv (fd, iov, count)) <= 0)
- { /* enet returns EOF (0) */
- #ifndef EBADMSG /* a stream will return EAGAIN */
- if (count == 0 || errno == EWOULDBLOCK)
- errno = EAGAIN;
- #endif
- return (-1);
- }
-
- if ((count -= ETHER_PKT) < 0)
- {
- #ifdef EBADMSG
- errno = EBADMSG; /* XXX readv() can also return this */
- #else
- errno = EMSGSIZE; /* XXX message isn't really too long */
- #endif
- }
-
- return (count);
- }
-