Here's a rewrite of my connect_sync() changes to use connect_wait()
instead.  Unlike the version in the connect(2) manual, this one
returns EINTR when interrupted by a signal which is probably better.

 - todd

Index: usr.bin/ftp/extern.h
===================================================================
RCS file: /cvs/src/usr.bin/ftp/extern.h,v
retrieving revision 1.43
diff -u -p -u -r1.43 extern.h
--- usr.bin/ftp/extern.h        18 Aug 2016 16:23:06 -0000      1.43
+++ usr.bin/ftp/extern.h        19 Aug 2016 21:54:32 -0000
@@ -62,7 +62,6 @@
  */
 
 #include <sys/types.h>
-#include <sys/socket.h>
 
 void   abort_remote(FILE *);
 void   abortpt(int);
@@ -76,7 +75,7 @@ void  cmdabort(int);
 void   cmdscanner(int);
 int    command(const char *, ...);
 int    confirm(const char *, const char *);
-int    connect_sync(int, const struct sockaddr *, socklen_t);
+int    connect_wait(int);
 FILE   *dataconn(const char *);
 int    foregroundproc(void);
 int    fileindir(const char *, const char *);
Index: usr.bin/ftp/fetch.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.148
diff -u -p -u -r1.148 fetch.c
--- usr.bin/ftp/fetch.c 18 Aug 2016 16:23:06 -0000      1.148
+++ usr.bin/ftp/fetch.c 19 Aug 2016 22:00:26 -0000
@@ -557,8 +557,12 @@ noslash:
                }
 #endif /* !SMALL */
 
-again:
-               if (connect_sync(s, res->ai_addr, res->ai_addrlen) < 0) {
+               error = connect(s, res->ai_addr, res->ai_addrlen);
+               while (error != 0) {
+                       if (errno == EINTR) {
+                               error = connect_wait(s);
+                               continue;
+                       }
                        save_errno = errno;
                        close(s);
                        errno = save_errno;
Index: usr.bin/ftp/ftp.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/ftp.c,v
retrieving revision 1.98
diff -u -p -u -r1.98 ftp.c
--- usr.bin/ftp/ftp.c   18 Aug 2016 16:23:06 -0000      1.98
+++ usr.bin/ftp/ftp.c   19 Aug 2016 22:02:35 -0000
@@ -219,8 +219,12 @@ hookup(char *host, char *port)
                        }
                }
 #endif /* !SMALL */
-               error = connect_sync(s, res->ai_addr, res->ai_addrlen);
-               if (error) {
+               error = connect(s, res->ai_addr, res->ai_addrlen);
+               while (error != 0) {
+                       if (errno == EINTR) {
+                               error = connect_wait(s);
+                               continue;
+                       }
                        /* this "if" clause is to prevent print warning twice */
                        if (verbose && res->ai_next) {
                                if (getnameinfo(res->ai_addr, res->ai_addrlen,
@@ -235,11 +239,12 @@ hookup(char *host, char *port)
                        close(s);
                        errno = error;
                        s = -1;
-                       continue;
+                       break;
                }
 
                /* finally we got one */
-               break;
+               if (error == 0)
+                       break;
        }
        if (s < 0) {
                warn("%s", cause);
@@ -1514,8 +1519,13 @@ reinit:
                } else
                        goto bad;
 
-               if (connect_sync(data, (struct sockaddr *)&data_addr,
-                           data_addr.su_len) < 0) {
+               error = connect(data, (struct sockaddr *)&data_addr,
+                   data_addr.su_len);
+               while (error != 0) {
+                       if (errno == EINTR) {
+                               error = connect_wait(data);
+                               continue;
+                       }
                        if (activefallback) {
                                (void)close(data);
                                data = -1;
Index: usr.bin/ftp/util.c
===================================================================
RCS file: /cvs/src/usr.bin/ftp/util.c,v
retrieving revision 1.80
diff -u -p -u -r1.80 util.c
--- usr.bin/ftp/util.c  18 Aug 2016 16:23:06 -0000      1.80
+++ usr.bin/ftp/util.c  19 Aug 2016 22:03:10 -0000
@@ -67,6 +67,7 @@
  * FTP User Program -- Misc support routines
  */
 #include <sys/ioctl.h>
+#include <sys/socket.h>
 #include <sys/time.h>
 #include <arpa/ftp.h>
 
@@ -1070,35 +1071,25 @@ controlediting(void)
 #endif /* !SMALL */
 
 /*
- * Wrapper for connect(2) that restarts the syscall when
- * interrupted and operates synchronously.
+ * Wait for an asynchronous connect(2) attempt to finish.
  */
 int
-connect_sync(int s, const struct sockaddr *name, socklen_t namelen)
+connect_wait(int s)
 {
        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;
+
+       if (poll(pfd, 1, -1) == -1)
+               return -1;
+       if (getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
+               return -1;
+       if (error != 0) {
+               errno = error;
+               return -1;
        }
-       return (error ? -1 : 0);
+       return 0;
 }

Reply via email to