Hi! I've come up with some patches regarding the timeout setting on Windows (which doesn't work right now).
The first patch correctly handles timeout on send()/recv() operations. --- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700 +++ msmtp/src/net.c 2018-06-09 18:03:35.407374256 +0700 @@ -179,7 +179,7 @@ { #ifdef W32_NATIVE int e = WSAGetLastError(); - if (e == WSAEWOULDBLOCK) + if (e == WSAETIMEDOUT) { *errstr = xasprintf(_("network read error: %s"), _("the operation timed out")); @@ -226,7 +226,7 @@ { #ifdef W32_NATIVE int e = WSAGetLastError(); - if (e == WSAEWOULDBLOCK) + if (e == WSAETIMEDOUT) { *errstr = xasprintf(_("network write error: %s"), _("the operation timed out")) The second patch implements timeout on connect() for Windows. I also removed the unnecessary rset variable (it doesn't matter for select() on connect()). --- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700 +++ msmtp/src/net.c 2018-06-09 18:23:11.721796148 +0700 @@ -319,16 +319,17 @@ int timeout) { #ifdef W32_NATIVE - /* TODO: I don't know how to do this on Win32. Please send a patch. */ - return connect(fd, serv_addr, addrlen); -#else /* UNIX or DJGPP */ - + u_long flags; + DWORD err; + int optlen; + fd_set eset; +#else int flags; - struct timeval tv; - fd_set rset; - fd_set wset; int err; socklen_t optlen; +#endif + struct timeval tv; + fd_set wset; if (timeout <= 0) { @@ -337,8 +338,13 @@ else { /* make socket non-blocking */ +#ifdef W32_NATIVE + flags = 1; + if (ioctlsocket(fd, FIONBIO, &flags) == SOCKET_ERROR) +#else flags = fcntl(fd, F_GETFL, 0); if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) +#endif { return -1; } @@ -346,51 +352,75 @@ /* start connect */ if (connect(fd, serv_addr, addrlen) < 0) { +#ifdef W32_NATIVE + if (WSAGetLastError() != WSAEWOULDBLOCK) +#else if (errno != EINPROGRESS) +#endif { return -1; } tv.tv_sec = timeout; tv.tv_usec = 0; - FD_ZERO(&rset); FD_ZERO(&wset); - FD_SET(fd, &rset); FD_SET(fd, &wset); +#ifdef W32_NATIVE + FD_ZERO(&eset); + FD_SET(fd, &eset); +#endif /* wait for connect() to finish */ - if ((err = select(fd + 1, &rset, &wset, NULL, &tv)) <= 0) +#ifdef W32_NATIVE + /* In case of an error on connect(), eset will be affected instead + * of wset (on Windows only). */ + if ((err = select(fd + 1, NULL, &wset, &eset, &tv)) <= 0) +#else + if ((err = select(fd + 1, NULL, &wset, NULL, &tv)) <= 0) +#endif { /* errno is already set if err < 0 */ if (err == 0) { +#ifdef W32_NATIVE + WSASetLastError(WSAETIMEDOUT); +#else errno = ETIMEDOUT; +#endif } return -1; } /* test for success, set errno */ - optlen = sizeof(int); + optlen = sizeof(err); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen) < 0) { return -1; } if (err != 0) { +#ifdef W32_NATIVE + WSASetLastError(err); +#else errno = err; +#endif return -1; } } /* restore blocking mode */ +#ifdef W32_NATIVE + flags = 0; + if (ioctlsocket(fd, FIONBIO, &flags) == SOCKET_ERROR) +#else if (fcntl(fd, F_SETFL, flags) == -1) +#endif { return -1; } return 0; } -#endif /* UNIX */ } And the third patch just closes Windows sockets properly. --- msmtp-1.6.6/src/net.c 2016-11-11 15:12:04.000000000 +0700 +++ msmtp/src/net.c 2018-06-09 18:38:52.920735844 +0700 @@ -682,7 +712,7 @@ failure_errno = errno; } #endif - close(fd); + net_close_socket(fd); fd = -1; continue; } I've tested the patches mildly on both Windows 7 and Wine. ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ msmtp-users mailing list msmtp-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/msmtp-users