File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libpdel / io / timeout_fp.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:25:53 2012 UTC (13 years, 1 month ago) by misho
Branches: libpdel, MAIN
CVS tags: v0_5_3, HEAD
libpdel

    1: 
    2: /*
    3:  * Copyright (c) 2001-2002 Packet Design, LLC.
    4:  * All rights reserved.
    5:  * 
    6:  * Subject to the following obligations and disclaimer of warranty,
    7:  * use and redistribution of this software, in source or object code
    8:  * forms, with or without modifications are expressly permitted by
    9:  * Packet Design; provided, however, that:
   10:  * 
   11:  *    (i)  Any and all reproductions of the source or object code
   12:  *         must include the copyright notice above and the following
   13:  *         disclaimer of warranties; and
   14:  *    (ii) No rights are granted, in any manner or form, to use
   15:  *         Packet Design trademarks, including the mark "PACKET DESIGN"
   16:  *         on advertising, endorsements, or otherwise except as such
   17:  *         appears in the above copyright notice or in the software.
   18:  * 
   19:  * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
   20:  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
   21:  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
   22:  * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
   23:  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
   24:  * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
   25:  * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
   26:  * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
   27:  * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
   28:  * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
   29:  * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
   30:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
   31:  * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
   32:  * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
   33:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   34:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
   35:  * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
   36:  * THE POSSIBILITY OF SUCH DAMAGE.
   37:  *
   38:  * Author: Archie Cobbs <archie@freebsd.org>
   39:  */
   40: 
   41: #include <sys/types.h>
   42: #include <sys/time.h>
   43: 
   44: #include <stdio.h>
   45: #include <stdlib.h>
   46: #include <stdarg.h>
   47: #include <syslog.h>
   48: #include <string.h>
   49: #include <unistd.h>
   50: #include <errno.h>
   51: #include <poll.h>
   52: 
   53: #include "structs/structs.h"
   54: #include "structs/type/array.h"
   55: 
   56: #include "io/timeout_fp.h"
   57: #include "util/typed_mem.h"
   58: 
   59: #define MEM_TYPE	"timeout_fp"
   60: 
   61: struct fdt_info {
   62: 	int	fd;
   63: 	int	timeout;
   64: };
   65: 
   66: typedef int	fun_reader(void *cookie, char *buf, int len);
   67: typedef int	fun_writer(void *cookie, const char *buf, int len);
   68: 
   69: /*
   70:  * Internal functions
   71:  */
   72: static int 	timeout_fp_readwrite(struct fdt_info *fdt,
   73: 			char *buf, int len, int wr);
   74: static int	timeout_fp_close(void *cookie);
   75: 
   76: static fun_reader	timeout_fp_read;
   77: static fun_writer	timeout_fp_write;
   78: 
   79: /*
   80:  * Same as fdopen(3) but with a timeout.
   81:  */
   82: FILE *
   83: timeout_fdopen(int fd, const char *mode, int timeout)
   84: {
   85: 	fun_reader *reader = NULL;
   86: 	fun_writer *writer = NULL;
   87: 	struct fdt_info *fdt;
   88: 	const char *s;
   89: 	FILE *fp;
   90: 
   91: 	/* If no timeout, fall back to normal case */
   92: 	if (timeout <= 0)
   93: 		return (fdopen(fd, mode));
   94: 
   95: 	/* Create the info structure */
   96: 	if ((fdt = MALLOC(MEM_TYPE, sizeof(*fdt))) == NULL)
   97: 		return (NULL);
   98: 	memset(fdt, 0, sizeof(*fdt));
   99: 	fdt->fd = fd;
  100: 	fdt->timeout = timeout;
  101: 
  102: 	/* Get reader & writer functions */
  103: 	for (s = mode; *s != '\0'; s++) {
  104: 		switch (*s) {
  105: 		case 'r':
  106: 			reader = timeout_fp_read;
  107: 			break;
  108: 		case 'w':
  109: 		case 'a':
  110: 			writer = timeout_fp_write;
  111: 			break;
  112: 		case '+':
  113: 			reader = timeout_fp_read;
  114: 			writer = timeout_fp_write;
  115: 			break;
  116: 		}
  117: 	}
  118: 
  119: 	/* Get FILE * wrapper */
  120: 	if ((fp = funopen(fdt, reader, writer,
  121: 	    NULL, timeout_fp_close)) == NULL) {
  122: 		FREE(MEM_TYPE, fdt);
  123: 		return (NULL);
  124: 	}
  125: 
  126: 	/* Done */
  127: 	return (fp);
  128: }
  129: 
  130: static int
  131: timeout_fp_read(void *cookie, char *buf, int len)
  132: {
  133: 	struct fdt_info *const fdt = cookie;
  134: 
  135: 	return (timeout_fp_readwrite(fdt, buf, len, 0));
  136: }
  137: 
  138: static int
  139: timeout_fp_write(void *cookie, const char *buf, int len)
  140: {
  141: 	struct fdt_info *const fdt = cookie;
  142: 
  143: 	return (timeout_fp_readwrite(fdt, (char *)buf, len, 1));
  144: }
  145: 
  146: /*
  147:  * Do the threaded read or write depending on the value of 'wr'.
  148:  */
  149: static int
  150: timeout_fp_readwrite(struct fdt_info *fdt, char *buf, int len, int wr)
  151: {
  152: 	struct pollfd pfd;
  153: 	int nfds;
  154: 
  155: 	/* Set up read/write poll(2) event */
  156: 	memset(&pfd, 0, sizeof(pfd));
  157: 	pfd.fd = fdt->fd;
  158: 	pfd.events = wr ? POLLWRNORM : POLLRDNORM;
  159: 
  160: 	/* Wait for readability or writability */
  161: 	if ((nfds = poll(&pfd, 1, fdt->timeout * 1000)) == -1)
  162: 		return (-1);
  163: 
  164: 	/* Check for timeout */
  165: 	if (nfds == 0) {
  166: 		errno = ETIMEDOUT;
  167: 		return (-1);
  168: 	}
  169: 
  170: 	/* Do I/O */
  171: 	return (wr ? write(fdt->fd, buf, len) : read(fdt->fd, buf, len));
  172: }
  173: 
  174: /*
  175:  * Closer for timeout_fp streams.
  176:  */
  177: static int
  178: timeout_fp_close(void *cookie)
  179: {
  180: 	struct fdt_info *const fdt = cookie;
  181: 	int r;
  182: 
  183: 	r = close(fdt->fd);
  184: 	FREE(MEM_TYPE, fdt);
  185: 	return (r);
  186: }
  187: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>