POSIX says connect(2) does not restart so we need to do the same
kind of dance as async connect(2).
- todd
Index: usr.bin/ftp/ftp.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.c,v
retrieving revision 1.96
diff -u -p -u -r1.96 ftp.c
--- usr.bin/ftp/ftp.c 16 Mar 2016 15:41:11 -0000 1.96
+++ usr.bin/ftp/ftp.c 8 Aug 2016 18:56:33 -0000
@@ -108,6 +108,36 @@ off_t restart_point = 0;
FILE *cin, *cout;
+static int
+connect_sync(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct pollfd pfd[1];
+ int error = 0;
+ socklen_t len = sizeof(error);
+
+ if (connect(s, name, namelen) < 0) {
+ if (errno != EINTR)
+ return -1;
+ }
+
+ /* An interrupted connect(2) continues asyncronously. */
+ pfd[0].fd = s;
+ pfd[0].events = POLLOUT;
+ for (;;) {
+ if (poll(pfd, 1, -1) == -1) {
+ if (errno != EINTR)
+ return -1;
+ continue;
+ }
+ if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+ return -1;
+ if (error != 0)
+ errno = error;
+ break;
+ }
+ return (error ? -1 : 0);
+}
+
char *
hookup(char *host, char *port)
{
@@ -219,10 +249,7 @@ hookup(char *host, char *port)
}
}
#endif /* !SMALL */
- while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
- && errno == EINTR) {
- ;
- }
+ error = connect_sync(s, res->ai_addr, res->ai_addrlen);
if (error) {
/* this "if" clause is to prevent print warning twice */
if (verbose && res->ai_next) {
@@ -1517,10 +1544,8 @@ reinit:
} else
goto bad;
- while (connect(data, (struct sockaddr *)&data_addr,
+ if (connect_sync(data, (struct sockaddr *)&data_addr,
data_addr.su_len) < 0) {
- if (errno == EINTR)
- continue;
if (activefallback) {
(void)close(data);
data = -1;