1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
/* $NetBSD: write_wait.c,v 1.1.1.3 2007/05/19 16:28:50 heas Exp $ */
/*++
/* NAME
/* write_wait 3
/* SUMMARY
/* wait until descriptor becomes writable
/* SYNOPSIS
/* #include <iostuff.h>
/*
/* int write_wait(fd, timeout)
/* int fd;
/* int timeout;
/* DESCRIPTION
/* write_wait() blocks the current process until the specified file
/* descriptor becomes writable, or until the deadline is exceeded.
/*
/* Arguments:
/* .IP fd
/* File descriptor in the range 0..FD_SETSIZE.
/* .IP timeout
/* If positive, deadline in seconds. A zero value effects a poll.
/* A negative value means wait until something happens.
/* DIAGNOSTICS
/* Panic: interface violation. All system call errors are fatal.
/*
/* A zero result means success. When the specified deadline is
/* exceeded, write_wait() returns -1 and sets errno to ETIMEDOUT.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#ifdef USE_SYSV_POLL
#include <poll.h>
#endif
#ifdef USE_SYS_SELECT_H
#include <sys/select.h>
#endif
/* Utility library. */
#include <msg.h>
#include <iostuff.h>
/* write_wait - block with timeout until file descriptor is writable */
int write_wait(int fd, int timeout)
{
#ifndef USE_SYSV_POLL
fd_set write_fds;
fd_set except_fds;
struct timeval tv;
struct timeval *tp;
/*
* Sanity checks.
*/
if (FD_SETSIZE <= fd)
msg_panic("descriptor %d does not fit FD_SETSIZE %d", fd, FD_SETSIZE);
/*
* Guard the write() with select() so we do not depend on alarm() and on
* signal() handlers. Restart the select when interrupted by some signal.
* Some select() implementations may reduce the time to wait when
* interrupted, which is exactly what we want.
*/
FD_ZERO(&write_fds);
FD_SET(fd, &write_fds);
FD_ZERO(&except_fds);
FD_SET(fd, &except_fds);
if (timeout >= 0) {
tv.tv_usec = 0;
tv.tv_sec = timeout;
tp = &tv;
} else {
tp = 0;
}
for (;;) {
switch (select(fd + 1, (fd_set *) 0, &write_fds, &except_fds, tp)) {
case -1:
if (errno != EINTR)
msg_fatal("select: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
return (0);
}
}
#else
/*
* System-V poll() is optimal for polling a few descriptors.
*/
struct pollfd pollfd;
#define WAIT_FOR_EVENT (-1)
pollfd.fd = fd;
pollfd.events = POLLOUT;
for (;;) {
switch (poll(&pollfd, 1, timeout < 0 ?
WAIT_FOR_EVENT : timeout * 1000)) {
case -1:
if (errno != EINTR)
msg_fatal("poll: %m");
continue;
case 0:
errno = ETIMEDOUT;
return (-1);
default:
if (pollfd.revents & POLLNVAL)
msg_fatal("poll: %m");
return (0);
}
}
#endif
}
|