xref: /openbsd-src/usr.bin/sendbug/atomicio.c (revision f4faee9106dab4458d5d3326f876cd772c8e31da)
1*f4faee91Sderaadt /* $OpenBSD: atomicio.c,v 1.4 2012/12/04 02:24:47 deraadt Exp $ */
25ae6585fSray /*
35ae6585fSray  * Copyright (c) 2006 Damien Miller. All rights reserved.
45ae6585fSray  * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
55ae6585fSray  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
65ae6585fSray  * All rights reserved.
75ae6585fSray  *
85ae6585fSray  * Redistribution and use in source and binary forms, with or without
95ae6585fSray  * modification, are permitted provided that the following conditions
105ae6585fSray  * are met:
115ae6585fSray  * 1. Redistributions of source code must retain the above copyright
125ae6585fSray  *    notice, this list of conditions and the following disclaimer.
135ae6585fSray  * 2. Redistributions in binary form must reproduce the above copyright
145ae6585fSray  *    notice, this list of conditions and the following disclaimer in the
155ae6585fSray  *    documentation and/or other materials provided with the distribution.
165ae6585fSray  *
175ae6585fSray  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
185ae6585fSray  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
195ae6585fSray  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
205ae6585fSray  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
215ae6585fSray  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
225ae6585fSray  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235ae6585fSray  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245ae6585fSray  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255ae6585fSray  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
265ae6585fSray  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275ae6585fSray  */
285ae6585fSray 
295ae6585fSray #include <errno.h>
3062f5b9b7Stobias #include <poll.h>
3162f5b9b7Stobias #include <unistd.h>
325ae6585fSray 
335ae6585fSray #include "atomicio.h"
345ae6585fSray 
355ae6585fSray /*
365ae6585fSray  * ensure all of data on socket comes through. f==read || f==vwrite
375ae6585fSray  */
385ae6585fSray size_t
atomicio(ssize_t (* f)(int,void *,size_t),int fd,void * _s,size_t n)395ae6585fSray atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
405ae6585fSray {
415ae6585fSray 	char *s = _s;
425ae6585fSray 	size_t pos = 0;
435ae6585fSray 	ssize_t res;
4462f5b9b7Stobias 	struct pollfd pfd;
455ae6585fSray 
4662f5b9b7Stobias 	pfd.fd = fd;
4762f5b9b7Stobias 	pfd.events = f == read ? POLLIN : POLLOUT;
485ae6585fSray 	while (n > pos) {
495ae6585fSray 		res = (f) (fd, s + pos, n - pos);
505ae6585fSray 		switch (res) {
515ae6585fSray 		case -1:
5262f5b9b7Stobias 			if (errno == EINTR)
535ae6585fSray 				continue;
5462f5b9b7Stobias 			if (errno == EAGAIN) {
5562f5b9b7Stobias 				(void)poll(&pfd, 1, -1);
5662f5b9b7Stobias 				continue;
5762f5b9b7Stobias 			}
585ae6585fSray 			return 0;
595ae6585fSray 		case 0:
605ae6585fSray 			errno = EPIPE;
615ae6585fSray 			return pos;
625ae6585fSray 		default:
635ae6585fSray 			pos += (size_t)res;
645ae6585fSray 		}
655ae6585fSray 	}
665ae6585fSray 	return (pos);
675ae6585fSray }
68