/*
 * Copyright (c) 2002, 2005 Sendmail, Inc. and its suppliers.
 *      All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: write_wait.c,v 1.7 2005/11/28 18:59:59 ca Exp $")
#include "sm/assert.h"
#include "sm/types.h"
#include "sm/time.h"
#include "sm/fdset.h"
#include "sm/io.h"
#include "io-int.h"
#include "sm/error.h"

/*
**  SM_WRITE_WAIT -- wait for fd to become ready for writing (with timeout)
**
**	Parameters:
**		fd -- file descriptor to write data to
**		timeout -- timeout
**
**	Returns:
**		= 0: fd ready for writing
**		< 0: usual sm_error code
*/

sm_ret_T
sm_write_wait(int fd, int timeout)
{
#if HAVE_SELECT
	int r;
	fd_set write_fds;
	fd_set except_fds;
	struct timeval tv;
	struct timeval *tp;

	/* XXX could switch to poll... */
	/* XXX return an error instead of aborting? */
	SM_REQUIRE(FD_SETSIZE > fd);

	FD_ZERO(&write_fds);
	SM_FD_SET(fd, &write_fds);
	FD_ZERO(&except_fds);
	SM_FD_SET(fd, &except_fds);
	if (timeout >= 0)
	{
		tv.tv_usec = 0;
		tv.tv_sec = timeout;
		tp = &tv;
	}
	else
		tp = NULL;

	for (;;)
	{
		r = select(fd + 1, (fd_set *) NULL, &write_fds, &except_fds,
			   tp);
		if (r == -1)
		{
			if (errno == EINTR)
				continue;
			else
				return sm_error_perm(SM_EM_IO, errno);
		}
		else if (r == 0)
			return sm_error_temp(SM_EM_IO, ETIMEDOUT);
		else
			return SM_SUCCESS;
	}
#else /* HAVE_SELECT */
/* XXX try poll ? */
#endif /* HAVE_SELECT */
}


syntax highlighted by Code2HTML, v. 0.9.1