-/* $OpenBSD: extern.h,v 1.52 2021/02/02 12:58:42 robert Exp $ */
+/* $OpenBSD: extern.h,v 1.53 2022/09/15 12:47:10 millert Exp $ */
/* $NetBSD: extern.h,v 1.17 1997/08/18 10:20:19 lukem Exp $ */
/*
*/
#include <sys/types.h>
+#include <sys/socket.h>
void abort_remote(FILE *);
void abortpt(int);
void cmdscanner(int);
int command(const char *, ...);
int confirm(const char *, const char *);
-int connect_wait(int);
FILE *dataconn(const char *);
int foregroundproc(void);
int fileindir(const char *, const char *);
void setpeer(int, char **);
void setttywidth(int);
char *slurpstring(void);
+int timed_connect(int s, const struct sockaddr *, socklen_t, int);
__dead void usage(void);
-/* $OpenBSD: fetch.c,v 1.209 2022/09/08 11:12:44 claudio Exp $ */
+/* $OpenBSD: fetch.c,v 1.210 2022/09/15 12:47:10 millert Exp $ */
/* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */
/*-
return (epath);
}
-/* ARGSUSED */
-static void
-tooslow(int signo)
-{
- dprintf(STDERR_FILENO, "%s: connect taking too long\n", __progname);
- _exit(2);
-}
-
/*
* Copy a local file (used by the OpenBSD installer).
* Returns -1 on failure, 0 on success
}
#endif /* !SMALL */
- if (connect_timeout) {
- (void)signal(SIGALRM, tooslow);
- alarmtimer(connect_timeout);
- }
-
- for (error = connect(fd, res->ai_addr, res->ai_addrlen);
- error != 0 && errno == EINTR; error = connect_wait(fd))
- continue;
+ error = timed_connect(fd, res->ai_addr, res->ai_addrlen,
+ connect_timeout);
if (error != 0) {
save_errno = errno;
close(fd);
}
#endif
- if (connect_timeout) {
- signal(SIGALRM, SIG_DFL);
- alarmtimer(0);
- }
-
/*
* Construct and send the request. Proxy requests don't want leading /.
*/
{
const char errmsg[] = "\nfetch aborted.\n";
- alarmtimer(0);
write(fileno(ttyout), errmsg, sizeof(errmsg) - 1);
longjmp(httpabort, 1);
}
-.\" $OpenBSD: ftp.1,v 1.123 2022/03/27 20:09:12 naddy Exp $
+.\" $OpenBSD: ftp.1,v 1.124 2022/09/15 12:47:10 millert Exp $
.\" $NetBSD: ftp.1,v 1.22 1997/08/18 10:20:22 lukem Exp $
.\"
.\" Copyright (c) 1985, 1989, 1990, 1993
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
-.Dd $Mdocdate: March 27 2022 $
+.Dd $Mdocdate: September 15 2022 $
.Dt FTP 1
.Os
.Sh NAME
to show all responses from the remote server, as well
as report on data transfer statistics.
.It Fl w Ar seconds
-For URL format connections to HTTP/HTTPS servers, abort a
-slow connection after
-.Ar seconds .
+Wait for
+.Ar seconds
+for the remote server to connect before giving up.
.El
.Pp
The host with which
-/* $OpenBSD: ftp.c,v 1.107 2019/11/18 04:37:35 deraadt Exp $ */
+/* $OpenBSD: ftp.c,v 1.108 2022/09/15 12:47:10 millert Exp $ */
/* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */
/*
}
}
#endif /* !SMALL */
- for (error = connect(s, res->ai_addr, res->ai_addrlen);
- error != 0 && errno == EINTR; error = connect_wait(s))
- continue;
+ error = timed_connect(s, res->ai_addr, res->ai_addrlen,
+ connect_timeout);
if (error != 0) {
/* this "if" clause is to prevent print warning twice */
if (verbose && res->ai_next) {
} else
goto bad;
- for (error = connect(data, &data_addr.sa, data_addr.sa.sa_len);
- error != 0 && errno == EINTR;
- error = connect_wait(data))
- continue;
+ error = timed_connect(data, &data_addr.sa, data_addr.sa.sa_len,
+ connect_timeout);
if (error != 0) {
if (activefallback) {
(void)close(data);
-/* $OpenBSD: util.c,v 1.95 2021/02/02 12:58:42 robert Exp $ */
+/* $OpenBSD: util.c,v 1.96 2022/09/15 12:47:10 millert Exp $ */
/* $NetBSD: util.c,v 1.12 1997/08/18 10:20:27 lukem Exp $ */
/*-
}
#endif /* !SMALL */
+/*
+ * connect(2) with an optional timeout if secs > 0.
+ */
+int
+timed_connect(int s, const struct sockaddr *name, socklen_t namelen, int secs)
+{
+ struct timespec now, target, timebuf, *timeout = NULL;
+ int flags, nready, optval, ret = -1;
+ socklen_t optlen;
+ struct pollfd pfd;
+
+ if (secs > 0) {
+ timebuf.tv_sec = secs;
+ timebuf.tv_nsec = 0;
+ timeout = &timebuf;
+ clock_gettime(CLOCK_MONOTONIC, &target);
+ timespecadd(&target, timeout, &target);
+ }
+
+ flags = fcntl(s, F_GETFL, 0);
+ if (flags == -1) {
+ warn("fcntl(F_GETFL)");
+ return -1;
+ }
+ if (!(flags & O_NONBLOCK)) {
+ if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1) {
+ warn("fcntl(F_SETFL)");
+ return -1;
+ }
+ }
+
+ ret = connect(s, name, namelen);
+ if (ret == 0 || errno != EINPROGRESS)
+ goto done;
+
+ for (;;) {
+ pfd.fd = s;
+ pfd.events = POLLOUT;
+ nready = ppoll(&pfd, 1, timeout, NULL);
+ switch (nready) {
+ case -1:
+ if (errno != EINTR && errno != EAGAIN) {
+ warn("ppoll");
+ goto done;
+ }
+ if (timeout == NULL)
+ continue;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ timespecsub(&now, &target, timeout);
+ if (timeout->tv_sec >= 0)
+ continue;
+ /* FALLTHROUGH */
+ case 0:
+ errno = ETIMEDOUT;
+ goto done;
+ default:
+ optlen = sizeof(optval);
+ ret = getsockopt(s, SOL_SOCKET, SO_ERROR, &optval,
+ &optlen);
+ if (ret == 0 && optval != 0) {
+ ret = -1;
+ errno = optval;
+ }
+ goto done;
+ }
+ }
+
+done:
+ if (!(flags & O_NONBLOCK)) {
+ if (fcntl(s, F_SETFL, flags) == -1) {
+ warn("fcntl(F_SETFL)");
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
/*
* Wait for an asynchronous connect(2) attempt to finish.
*/