Module Name:    src
Committed By:   bouyer
Date:           Tue Dec 17 21:07:59 UTC 2013

Modified Files:
        src/usr.bin/ftp [netbsd-6]: Makefile cmds.c cmdtab.c extern.h fetch.c
            ftp.1 ftp.c ftp_var.h main.c progressbar.c util.c version.h
Added Files:
        src/usr.bin/ftp [netbsd-6]: ssl.c ssl.h

Log Message:
Apply patch, requested by tron in ticket #997:
        usr.bin/ftp/Makefile                            patch
        usr.bin/ftp/cmds.c                              patch
        usr.bin/ftp/cmdtab.c                            patch
        usr.bin/ftp/extern.h                            patch
        usr.bin/ftp/fetch.c                             patch
        usr.bin/ftp/ftp.1                               patch
        usr.bin/ftp/ftp.c                               patch
        usr.bin/ftp/ftp_var.h                           patch
        usr.bin/ftp/main.c                              patch
        usr.bin/ftp/progressbar.c                       patch
        usr.bin/ftp/ssl.c                               patch
        usr.bin/ftp/ssl.h                               patch
        usr.bin/ftp/util.c                              patch
        usr.bin/ftp/version.h                           patch

Add HTTPS support to ftp(1).


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.35.4.1 src/usr.bin/ftp/Makefile
cvs rdiff -u -r1.134 -r1.134.2.1 src/usr.bin/ftp/cmds.c
cvs rdiff -u -r1.51 -r1.51.8.1 src/usr.bin/ftp/cmdtab.c
cvs rdiff -u -r1.79 -r1.79.4.1 src/usr.bin/ftp/extern.h
cvs rdiff -u -r1.195 -r1.195.2.1 src/usr.bin/ftp/fetch.c
cvs rdiff -u -r1.131 -r1.131.8.1 src/usr.bin/ftp/ftp.1
cvs rdiff -u -r1.163 -r1.163.2.1 src/usr.bin/ftp/ftp.c
cvs rdiff -u -r1.81 -r1.81.8.1 src/usr.bin/ftp/ftp_var.h
cvs rdiff -u -r1.120 -r1.120.2.1 src/usr.bin/ftp/main.c
cvs rdiff -u -r1.21 -r1.21.8.1 src/usr.bin/ftp/progressbar.c
cvs rdiff -u -r0 -r1.2.10.2 src/usr.bin/ftp/ssl.c
cvs rdiff -u -r0 -r1.1.10.2 src/usr.bin/ftp/ssl.h
cvs rdiff -u -r1.156 -r1.156.2.1 src/usr.bin/ftp/util.c
cvs rdiff -u -r1.82 -r1.82.8.1 src/usr.bin/ftp/version.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/ftp/Makefile
diff -u src/usr.bin/ftp/Makefile:1.35 src/usr.bin/ftp/Makefile:1.35.4.1
--- src/usr.bin/ftp/Makefile:1.35	Sun Aug 14 12:58:15 2011
+++ src/usr.bin/ftp/Makefile	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.35 2011/08/14 12:58:15 christos Exp $
+#	$NetBSD: Makefile,v 1.35.4.1 2013/12/17 21:07:59 bouyer Exp $
 #	from: @(#)Makefile	8.2 (Berkeley) 4/3/94
 
 .include <bsd.own.mk>
@@ -18,6 +18,12 @@ CPPFLAGS+=-DNO_EDITCOMPLETE -DNO_ABOUT -
 .else
 LDADD+=	-ledit -lterminfo
 DPADD+=	${LIBEDIT} ${LIBTERMINFO}
+.if (${MKCRYPTO} != "no")
+CPPFLAGS+= -DWITH_SSL
+SRCS+=ssl.c
+LDADD+= -lssl -lcrypto
+DPADD+= ${LIBSSL} ${LIBCRYPTO}
+.endif
 .endif
 
 .if (!defined(SMALLPROG) || defined(SMALLPROG_INET6)) && (${USE_INET6} != "no")

Index: src/usr.bin/ftp/cmds.c
diff -u src/usr.bin/ftp/cmds.c:1.134 src/usr.bin/ftp/cmds.c:1.134.2.1
--- src/usr.bin/ftp/cmds.c:1.134	Sun Jan 15 20:43:24 2012
+++ src/usr.bin/ftp/cmds.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: cmds.c,v 1.134 2012/01/15 20:43:24 christos Exp $	*/
+/*	$NetBSD: cmds.c,v 1.134.2.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
 #if 0
 static char sccsid[] = "@(#)cmds.c	8.6 (Berkeley) 10/9/94";
 #else
-__RCSID("$NetBSD: cmds.c,v 1.134 2012/01/15 20:43:24 christos Exp $");
+__RCSID("$NetBSD: cmds.c,v 1.134.2.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif
 #endif /* not lint */
 
@@ -2675,7 +2675,7 @@ setoption(int argc, char *argv[])
 		return;
 	}
 
-#define	OPTIONINDENT ((int) sizeof("http_proxy"))
+#define	OPTIONINDENT ((int) sizeof("https_proxy"))
 	if (argc == 1) {
 		for (o = optiontab; o->name != NULL; o++) {
 			fprintf(ttyout, "%-*s\t%s\n", OPTIONINDENT,

Index: src/usr.bin/ftp/cmdtab.c
diff -u src/usr.bin/ftp/cmdtab.c:1.51 src/usr.bin/ftp/cmdtab.c:1.51.8.1
--- src/usr.bin/ftp/cmdtab.c:1.51	Sun Apr 12 10:18:52 2009
+++ src/usr.bin/ftp/cmdtab.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: cmdtab.c,v 1.51 2009/04/12 10:18:52 lukem Exp $	*/
+/*	$NetBSD: cmdtab.c,v 1.51.8.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
 #if 0
 static char sccsid[] = "@(#)cmdtab.c	8.4 (Berkeley) 10/9/94";
 #else
-__RCSID("$NetBSD: cmdtab.c,v 1.51 2009/04/12 10:18:52 lukem Exp $");
+__RCSID("$NetBSD: cmdtab.c,v 1.51.8.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif
 #endif /* not lint */
 
@@ -298,6 +298,7 @@ struct option optiontab[] = {
 	{ "anonpass",	NULL },
 	{ "ftp_proxy",	NULL },
 	{ "http_proxy",	NULL },
+	{ "https_proxy",NULL },
 	{ "no_proxy",	NULL },
 	{ "pager",	NULL },
 	{ "prompt",	NULL },

Index: src/usr.bin/ftp/extern.h
diff -u src/usr.bin/ftp/extern.h:1.79 src/usr.bin/ftp/extern.h:1.79.4.1
--- src/usr.bin/ftp/extern.h:1.79	Fri Sep 16 15:39:26 2011
+++ src/usr.bin/ftp/extern.h	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: extern.h,v 1.79 2011/09/16 15:39:26 joerg Exp $	*/
+/*	$NetBSD: extern.h,v 1.79.4.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -239,7 +239,7 @@ void	unsetoption(int, char **);
 void	updatelocalcwd(void);
 void	updateremotecwd(void);
 void	user(int, char **);
-int	ftp_connect(int, const struct sockaddr *, socklen_t);
+int	ftp_connect(int, const struct sockaddr *, socklen_t, int);
 int	ftp_listen(int, int);
 int	ftp_poll(struct pollfd *, int, int);
 void   *ftp_malloc(size_t);

Index: src/usr.bin/ftp/fetch.c
diff -u src/usr.bin/ftp/fetch.c:1.195 src/usr.bin/ftp/fetch.c:1.195.2.1
--- src/usr.bin/ftp/fetch.c:1.195	Sat Dec 10 05:53:58 2011
+++ src/usr.bin/ftp/fetch.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: fetch.c,v 1.195 2011/12/10 05:53:58 lukem Exp $	*/
+/*	$NetBSD: fetch.c,v 1.195.2.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: fetch.c,v 1.195 2011/12/10 05:53:58 lukem Exp $");
+__RCSID("$NetBSD: fetch.c,v 1.195.2.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif /* not lint */
 
 /*
@@ -64,18 +64,23 @@ __RCSID("$NetBSD: fetch.c,v 1.195 2011/1
 #include <unistd.h>
 #include <time.h>
 
+#include "ssl.h"
 #include "ftp_var.h"
 #include "version.h"
 
 typedef enum {
 	UNKNOWN_URL_T=-1,
 	HTTP_URL_T,
+#ifdef WITH_SSL
+	HTTPS_URL_T,
+#endif
 	FTP_URL_T,
 	FILE_URL_T,
 	CLASSIC_URL_T
 } url_t;
 
 __dead static void	aborthttp(int);
+__dead static void	timeouthttp(int);
 #ifndef NO_AUTH
 static int	auth_url(const char *, char **, const char *, const char *);
 static void	base64_encode(const unsigned char *, size_t, unsigned char *);
@@ -100,7 +105,15 @@ static int	redirect_loop;
 #define	FILE_URL	"file://"	/* file URL prefix */
 #define	FTP_URL		"ftp://";	/* ftp URL prefix */
 #define	HTTP_URL	"http://";	/* http URL prefix */
+#ifdef WITH_SSL
+#define	HTTPS_URL	"https://";	/* https URL prefix */
 
+#define	IS_HTTP_TYPE(urltype) \
+	(((urltype) == HTTP_URL_T) || ((urltype) == HTTPS_URL_T))
+#else
+#define	IS_HTTP_TYPE(urltype) \
+	((urltype) == HTTP_URL_T)
+#endif
 
 /*
  * Determine if token is the next word in buf (case insensitive).
@@ -346,6 +359,13 @@ parse_url(const char *url, const char *d
 	} else if (STRNEQUAL(url, FILE_URL)) {
 		url += sizeof(FILE_URL) - 1;
 		*utype = FILE_URL_T;
+#ifdef WITH_SSL
+	} else if (STRNEQUAL(url, HTTPS_URL)) {
+		url += sizeof(HTTPS_URL) - 1;
+		*utype = HTTPS_URL_T;
+		*portnum = HTTPS_PORT;
+		tport = httpsport;
+#endif
 	} else {
 		warnx("Invalid %s `%s'", desc, url);
  cleanup_parse_url:
@@ -463,7 +483,7 @@ sigjmp_buf	httpabort;
 /*
  * Retrieve URL, via a proxy if necessary, using HTTP.
  * If proxyenv is set, use that for the proxy, otherwise try ftp_proxy or
- * http_proxy as appropriate.
+ * http_proxy/https_proxy as appropriate.
  * Supports HTTP redirects.
  * Returns 1 on failure, 0 on completed xfer, -1 if ftp connection
  * is still open (e.g, ftp xfer with trailing /)
@@ -473,8 +493,10 @@ fetch_url(const char *url, const char *p
 {
 	struct addrinfo		hints, *res, *res0 = NULL;
 	int			error;
-	sigfunc volatile	oldintr;
-	sigfunc volatile	oldintp;
+	sigfunc volatile	oldint;
+	sigfunc volatile	oldpipe;
+	sigfunc volatile	oldalrm;
+	sigfunc volatile	oldquit;
 	int volatile		s;
 	struct stat		sb;
 	int volatile		ischunked;
@@ -498,17 +520,22 @@ fetch_url(const char *url, const char *p
 	char			*puser, *ppass, *useragent;
 	off_t			hashbytes, rangestart, rangeend, entitylen;
 	int			(*volatile closefunc)(FILE *);
-	FILE			*volatile fin;
+	FETCH			*volatile fin;
 	FILE			*volatile fout;
+	const char		*volatile penv = proxyenv;
 	time_t			mtime;
 	url_t			urltype;
 	in_port_t		portnum;
+#ifdef WITH_SSL
+	void			*ssl;
+#endif
 
-	DPRINTF("fetch_url: `%s' proxyenv `%s'\n", url, STRorNULL(proxyenv));
+	DPRINTF("%s: `%s' proxyenv `%s'\n", __func__, url, STRorNULL(penv));
 
-	oldintr = oldintp = NULL;
+	oldquit = oldalrm = oldint = oldpipe = NULL;
 	closefunc = NULL;
-	fin = fout = NULL;
+	fin = NULL;
+	fout = NULL;
 	s = -1;
 	savefile = NULL;
 	auth = location = message = NULL;
@@ -516,6 +543,9 @@ fetch_url(const char *url, const char *p
 	rval = 1;
 	uuser = pass = host = path = decodedpath = puser = ppass = NULL;
 
+	if (sigsetjmp(httpabort, 1))
+		goto cleanup_fetch_url;
+
 	if (parse_url(url, "URL", &urltype, &uuser, &pass, &host, &port,
 	    &portnum, &path) == -1)
 		goto cleanup_fetch_url;
@@ -531,7 +561,7 @@ fetch_url(const char *url, const char *p
 			rval = fetch_ftp(url);
 			goto cleanup_fetch_url;
 		}
-		if (urltype != HTTP_URL_T || outfile == NULL)  {
+		if (!IS_HTTP_TYPE(urltype) || outfile == NULL)  {
 			warnx("Invalid URL (no file after host) `%s'", url);
 			goto cleanup_fetch_url;
 		}
@@ -549,7 +579,7 @@ fetch_url(const char *url, const char *p
 		else
 			savefile = ftp_strdup(decodedpath);
 	}
-	DPRINTF("fetch_url: savefile `%s'\n", savefile);
+	DPRINTF("%s: savefile `%s'\n", __func__, savefile);
 	if (EMPTYSTRING(savefile)) {
 		if (urltype == FTP_URL_T) {
 			rval = fetch_ftp(url);
@@ -571,17 +601,17 @@ fetch_url(const char *url, const char *p
 	}
 	if (urltype == FILE_URL_T) {		/* file:// URLs */
 		direction = "copied";
-		fin = fopen(decodedpath, "r");
+		fin = fetch_open(decodedpath, "r");
 		if (fin == NULL) {
 			warn("Can't open `%s'", decodedpath);
 			goto cleanup_fetch_url;
 		}
-		if (fstat(fileno(fin), &sb) == 0) {
+		if (fstat(fetch_fileno(fin), &sb) == 0) {
 			mtime = sb.st_mtime;
 			filesize = sb.st_size;
 		}
 		if (restart_point) {
-			if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
+			if (lseek(fetch_fileno(fin), restart_point, SEEK_SET) < 0) {
 				warn("Can't seek to restart `%s'",
 				    decodedpath);
 				goto cleanup_fetch_url;
@@ -594,18 +624,25 @@ fetch_url(const char *url, const char *p
 				    (LLT)restart_point);
 			fputs("\n", ttyout);
 		}
+		if (0 == rcvbuf_size) {
+			rcvbuf_size = 8 * 1024; /* XXX */
+		}
 	} else {				/* ftp:// or http:// URLs */
 		const char *leading;
 		int hasleading;
 
-		if (proxyenv == NULL) {
-			if (urltype == HTTP_URL_T)
-				proxyenv = getoptionvalue("http_proxy");
+		if (penv == NULL) {
+#ifdef WITH_SSL
+			if (urltype == HTTPS_URL_T)
+				penv = getoptionvalue("https_proxy");
+#endif
+			if (penv == NULL && IS_HTTP_TYPE(urltype))
+				penv = getoptionvalue("http_proxy");
 			else if (urltype == FTP_URL_T)
-				proxyenv = getoptionvalue("ftp_proxy");
+				penv = getoptionvalue("ftp_proxy");
 		}
 		direction = "retrieved";
-		if (! EMPTYSTRING(proxyenv)) {			/* use proxy */
+		if (! EMPTYSTRING(penv)) {			/* use proxy */
 			url_t purltype;
 			char *phost, *ppath;
 			char *pport, *no_proxy;
@@ -652,21 +689,20 @@ fetch_url(const char *url, const char *p
 			if (isproxy) {
 				if (restart_point) {
 					warnx("Can't restart via proxy URL `%s'",
-					    proxyenv);
+					    penv);
 					goto cleanup_fetch_url;
 				}
-				if (parse_url(proxyenv, "proxy URL", &purltype,
+				if (parse_url(penv, "proxy URL", &purltype,
 				    &puser, &ppass, &phost, &pport, &pportnum,
 				    &ppath) == -1)
 					goto cleanup_fetch_url;
 
-				if ((purltype != HTTP_URL_T
+				if ((!IS_HTTP_TYPE(purltype)
 				     && purltype != FTP_URL_T) ||
 				    EMPTYSTRING(phost) ||
 				    (! EMPTYSTRING(ppath)
 				     && strcmp(ppath, "/") != 0)) {
-					warnx("Malformed proxy URL `%s'",
-					    proxyenv);
+					warnx("Malformed proxy URL `%s'", penv);
 					FREEPTR(phost);
 					FREEPTR(pport);
 					FREEPTR(ppath);
@@ -690,8 +726,9 @@ fetch_url(const char *url, const char *p
 				FREEPTR(path);
 				path = ftp_strdup(url);
 				FREEPTR(ppath);
+				urltype = purltype;
 			}
-		} /* ! EMPTYSTRING(proxyenv) */
+		} /* ! EMPTYSTRING(penv) */
 
 		memset(&hints, 0, sizeof(hints));
 		hints.ai_flags = 0;
@@ -700,7 +737,7 @@ fetch_url(const char *url, const char *p
 		hints.ai_protocol = 0;
 		error = getaddrinfo(host, port, &hints, &res0);
 		if (error) {
-			warnx("Can't lookup `%s:%s': %s", host, port,
+			warnx("Can't LOOKUP `%s:%s': %s", host, port,
 			    (error == EAI_SYSTEM) ? strerror(errno)
 						  : gai_strerror(error));
 			goto cleanup_fetch_url;
@@ -709,6 +746,9 @@ fetch_url(const char *url, const char *p
 			host = res0->ai_canonname;
 
 		s = -1;
+#ifdef WITH_SSL
+		ssl = NULL;
+#endif
 		for (res = res0; res; res = res->ai_next) {
 			char	hname[NI_MAXHOST], sname[NI_MAXSERV];
 
@@ -734,12 +774,23 @@ fetch_url(const char *url, const char *p
 				continue;
 			}
 
-			if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+			if (ftp_connect(s, res->ai_addr, res->ai_addrlen,
+			    verbose || !res->ai_next) < 0) {
 				close(s);
 				s = -1;
 				continue;
 			}
 
+#ifdef WITH_SSL
+			if (urltype == HTTPS_URL_T) {
+				if ((ssl = fetch_start_ssl(s)) == NULL) {
+					close(s);
+					s = -1;
+					continue;
+				}
+			}
+#endif
+
 			/* success */
 			break;
 		}
@@ -749,7 +800,13 @@ fetch_url(const char *url, const char *p
 			goto cleanup_fetch_url;
 		}
 
-		fin = fdopen(s, "r+");
+		oldalrm = xsignal(SIGALRM, timeouthttp);
+		alarmtimer(quit_time ? quit_time : 60);
+		fin = fetch_fdopen(s, "r+");
+		fetch_set_ssl(fin, ssl);
+		alarmtimer(0);
+
+		alarmtimer(quit_time ? quit_time : 60);
 		/*
 		 * Construct and send the request.
 		 */
@@ -764,11 +821,11 @@ fetch_url(const char *url, const char *p
 				leading = ", ";
 				hasleading++;
 			}
-			fprintf(fin, "GET %s HTTP/1.0\r\n", path);
+			fetch_printf(fin, "GET %s HTTP/1.0\r\n", path);
 			if (flushcache)
-				fprintf(fin, "Pragma: no-cache\r\n");
+				fetch_printf(fin, "Pragma: no-cache\r\n");
 		} else {
-			fprintf(fin, "GET %s HTTP/1.1\r\n", path);
+			fetch_printf(fin, "GET %s HTTP/1.1\r\n", path);
 			if (strchr(host, ':')) {
 				char *h, *p;
 
@@ -781,18 +838,23 @@ fetch_url(const char *url, const char *p
 				    (p = strchr(h, '%')) != NULL) {
 					*p = '\0';
 				}
-				fprintf(fin, "Host: [%s]", h);
+				fetch_printf(fin, "Host: [%s]", h);
 				free(h);
 			} else
-				fprintf(fin, "Host: %s", host);
+				fetch_printf(fin, "Host: %s", host);
+#ifdef WITH_SSL
+			if ((urltype == HTTP_URL_T && portnum != HTTP_PORT) ||
+			    (urltype == HTTPS_URL_T && portnum != HTTPS_PORT))
+#else
 			if (portnum != HTTP_PORT)
-				fprintf(fin, ":%u", portnum);
-			fprintf(fin, "\r\n");
-			fprintf(fin, "Accept: */*\r\n");
-			fprintf(fin, "Connection: close\r\n");
+#endif
+				fetch_printf(fin, ":%u", portnum);
+			fetch_printf(fin, "\r\n");
+			fetch_printf(fin, "Accept: */*\r\n");
+			fetch_printf(fin, "Connection: close\r\n");
 			if (restart_point) {
 				fputs(leading, ttyout);
-				fprintf(fin, "Range: bytes=" LLF "-\r\n",
+				fetch_printf(fin, "Range: bytes=" LLF "-\r\n",
 				    (LLT)restart_point);
 				fprintf(ttyout, "restarting at " LLF,
 				    (LLT)restart_point);
@@ -800,12 +862,12 @@ fetch_url(const char *url, const char *p
 				hasleading++;
 			}
 			if (flushcache)
-				fprintf(fin, "Cache-Control: no-cache\r\n");
+				fetch_printf(fin, "Cache-Control: no-cache\r\n");
 		}
 		if ((useragent=getenv("FTPUSERAGENT")) != NULL) {
-			fprintf(fin, "User-Agent: %s\r\n", useragent);
+			fetch_printf(fin, "User-Agent: %s\r\n", useragent);
 		} else {
-			fprintf(fin, "User-Agent: %s/%s\r\n",
+			fetch_printf(fin, "User-Agent: %s/%s\r\n",
 			    FTP_PRODUCT, FTP_VERSION);
 		}
 		if (wwwauth) {
@@ -815,7 +877,7 @@ fetch_url(const char *url, const char *p
 				leading = ", ";
 				hasleading++;
 			}
-			fprintf(fin, "Authorization: %s\r\n", wwwauth);
+			fetch_printf(fin, "Authorization: %s\r\n", wwwauth);
 		}
 		if (proxyauth) {
 			if (verbose) {
@@ -824,18 +886,22 @@ fetch_url(const char *url, const char *p
 				leading = ", ";
 				hasleading++;
 			}
-			fprintf(fin, "Proxy-Authorization: %s\r\n", proxyauth);
+			fetch_printf(fin, "Proxy-Authorization: %s\r\n", proxyauth);
 		}
 		if (verbose && hasleading)
 			fputs(")\n", ttyout);
-		fprintf(fin, "\r\n");
-		if (fflush(fin) == EOF) {
+		fetch_printf(fin, "\r\n");
+		if (fetch_flush(fin) == EOF) {
 			warn("Writing HTTP request");
+			alarmtimer(0);
 			goto cleanup_fetch_url;
 		}
+		alarmtimer(0);
 
 				/* Read the response */
-		len = get_line(fin, buf, sizeof(buf), &errormsg);
+		alarmtimer(quit_time ? quit_time : 60);
+		len = fetch_getline(fin, buf, sizeof(buf), &errormsg);
+		alarmtimer(0);
 		if (len < 0) {
 			if (*errormsg == '\n')
 				errormsg++;
@@ -844,7 +910,7 @@ fetch_url(const char *url, const char *p
 		}
 		while (len > 0 && (ISLWS(buf[len-1])))
 			buf[--len] = '\0';
-		DPRINTF("fetch_url: received `%s'\n", buf);
+		DPRINTF("%s: received `%s'\n", __func__, buf);
 
 				/* Determine HTTP response code */
 		cp = strchr(buf, ' ');
@@ -859,7 +925,9 @@ fetch_url(const char *url, const char *p
 
 				/* Read the rest of the header. */
 		while (1) {
-			len = get_line(fin, buf, sizeof(buf), &errormsg);
+			alarmtimer(quit_time ? quit_time : 60);
+			len = fetch_getline(fin, buf, sizeof(buf), &errormsg);
+			alarmtimer(0);
 			if (len < 0) {
 				if (*errormsg == '\n')
 					errormsg++;
@@ -870,7 +938,7 @@ fetch_url(const char *url, const char *p
 				buf[--len] = '\0';
 			if (len == 0)
 				break;
-			DPRINTF("fetch_url: received `%s'\n", buf);
+			DPRINTF("%s: received `%s'\n", __func__, buf);
 
 		/*
 		 * Look for some headers
@@ -882,8 +950,8 @@ fetch_url(const char *url, const char *p
 				filesize = STRTOLL(cp, &ep, 10);
 				if (filesize < 0 || *ep != '\0')
 					goto improper;
-				DPRINTF("fetch_url: parsed len as: " LLF "\n",
-				    (LLT)filesize);
+				DPRINTF("%s: parsed len as: " LLF "\n",
+				    __func__, (LLT)filesize);
 
 			} else if (match_token(&cp, "Content-Range:")) {
 				if (! match_token(&cp, "bytes"))
@@ -954,8 +1022,8 @@ fetch_url(const char *url, const char *p
 
 			} else if (match_token(&cp, "Location:")) {
 				location = ftp_strdup(cp);
-				DPRINTF("fetch_url: parsed location as `%s'\n",
-				    cp);
+				DPRINTF("%s: parsed location as `%s'\n",
+				    __func__, cp);
 
 			} else if (match_token(&cp, "Transfer-Encoding:")) {
 				if (match_token(&cp, "binary")) {
@@ -970,19 +1038,20 @@ fetch_url(const char *url, const char *p
 					goto cleanup_fetch_url;
 				}
 				ischunked++;
-				DPRINTF("fetch_url: using chunked encoding\n");
+				DPRINTF("%s: using chunked encoding\n",
+				    __func__);
 
 			} else if (match_token(&cp, "Proxy-Authenticate:")
 				|| match_token(&cp, "WWW-Authenticate:")) {
 				if (! (token = match_token(&cp, "Basic"))) {
-					DPRINTF(
-			"fetch_url: skipping unknown auth scheme `%s'\n",
-						    token);
+					DPRINTF("%s: skipping unknown auth "
+					    "scheme `%s'\n", __func__, token);
 					continue;
 				}
 				FREEPTR(auth);
 				auth = ftp_strdup(token);
-				DPRINTF("fetch_url: parsed auth as `%s'\n", cp);
+				DPRINTF("%s: parsed auth as `%s'\n",
+				    __func__, cp);
 			}
 
 		}
@@ -1064,7 +1133,7 @@ fetch_url(const char *url, const char *p
 				apass = NULL;
 			}
 			if (auth_url(auth, authp, auser, apass) == 0) {
-				rval = fetch_url(url, proxyenv,
+				rval = fetch_url(url, penv,
 				    proxyauth, wwwauth);
 				memset(*authp, 0, strlen(*authp));
 				FREEPTR(*authp);
@@ -1085,7 +1154,7 @@ fetch_url(const char *url, const char *p
 	if (strcmp(savefile, "-") == 0) {
 		fout = stdout;
 	} else if (*savefile == '|') {
-		oldintp = xsignal(SIGPIPE, SIG_IGN);
+		oldpipe = xsignal(SIGPIPE, SIG_IGN);
 		fout = popen(savefile + 1, "w");
 		if (fout == NULL) {
 			warn("Can't execute `%s'", savefile + 1);
@@ -1121,10 +1190,8 @@ fetch_url(const char *url, const char *p
 	}
 
 			/* Trap signals */
-	if (sigsetjmp(httpabort, 1))
-		goto cleanup_fetch_url;
-	(void)xsignal(SIGQUIT, psummary);
-	oldintr = xsignal(SIGINT, aborthttp);
+	oldquit = xsignal(SIGQUIT, psummary);
+	oldint = xsignal(SIGINT, aborthttp);
 
 	assert(rcvbuf_size > 0);
 	if ((size_t)rcvbuf_size > bufsize) {
@@ -1136,6 +1203,10 @@ fetch_url(const char *url, const char *p
 
 	bytes = 0;
 	hashbytes = mark;
+	if (oldalrm) {
+		(void)xsignal(SIGALRM, oldalrm);
+		oldalrm = NULL;
+	}
 	progressmeter(-1);
 
 			/* Finally, suck down the file. */
@@ -1147,7 +1218,7 @@ fetch_url(const char *url, const char *p
 		lastchunk = 0;
 					/* read chunk-size */
 		if (ischunked) {
-			if (fgets(xferbuf, bufsize, fin) == NULL) {
+			if (fetch_getln(xferbuf, bufsize, fin) == NULL) {
 				warnx("Unexpected EOF reading chunk-size");
 				goto cleanup_fetch_url;
 			}
@@ -1182,7 +1253,7 @@ fetch_url(const char *url, const char *p
 				warnx("Unexpected data following chunk-size");
 				goto cleanup_fetch_url;
 			}
-			DPRINTF("fetch_url: got chunk-size of " LLF "\n",
+			DPRINTF("%s: got chunk-size of " LLF "\n", __func__,
 			    (LLT)chunksize);
 			if (chunksize == 0) {
 				lastchunk = 1;
@@ -1192,7 +1263,7 @@ fetch_url(const char *url, const char *p
 					/* transfer file or chunk */
 		while (1) {
 			struct timeval then, now, td;
-			off_t bufrem;
+			volatile off_t bufrem;
 
 			if (rate_get)
 				(void)gettimeofday(&then, NULL);
@@ -1200,7 +1271,7 @@ fetch_url(const char *url, const char *p
 			if (ischunked)
 				bufrem = MIN(chunksize, bufrem);
 			while (bufrem > 0) {
-				flen = fread(xferbuf, sizeof(char),
+				flen = fetch_read(xferbuf, sizeof(char),
 				    MIN((off_t)bufsize, bufrem), fin);
 				if (flen <= 0)
 					goto chunkdone;
@@ -1239,7 +1310,8 @@ fetch_url(const char *url, const char *p
 					/* read CRLF after chunk*/
  chunkdone:
 		if (ischunked) {
-			if (fgets(xferbuf, bufsize, fin) == NULL) {
+			if (fetch_getln(xferbuf, bufsize, fin) == NULL) {
+				alarmtimer(0);
 				warnx("Unexpected EOF reading chunk CRLF");
 				goto cleanup_fetch_url;
 			}
@@ -1259,7 +1331,7 @@ fetch_url(const char *url, const char *p
 			(void)putc('#', ttyout);
 		(void)putc('\n', ttyout);
 	}
-	if (ferror(fin)) {
+	if (fetch_error(fin)) {
 		warn("Reading file");
 		goto cleanup_fetch_url;
 	}
@@ -1291,12 +1363,16 @@ fetch_url(const char *url, const char *p
 	warnx("Improper response from `%s:%s'", host, port);
 
  cleanup_fetch_url:
-	if (oldintr)
-		(void)xsignal(SIGINT, oldintr);
-	if (oldintp)
-		(void)xsignal(SIGPIPE, oldintp);
+	if (oldint)
+		(void)xsignal(SIGINT, oldint);
+	if (oldpipe)
+		(void)xsignal(SIGPIPE, oldpipe);
+	if (oldalrm)
+		(void)xsignal(SIGALRM, oldalrm);
+	if (oldquit)
+		(void)xsignal(SIGQUIT, oldpipe);
 	if (fin != NULL)
-		fclose(fin);
+		fetch_close(fin);
 	else if (s != -1)
 		close(s);
 	if (closefunc != NULL && fout != NULL)
@@ -1329,12 +1405,32 @@ static void
 aborthttp(int notused)
 {
 	char msgbuf[100];
-	size_t len;
+	int len;
 
 	sigint_raised = 1;
 	alarmtimer(0);
-	len = strlcpy(msgbuf, "\nHTTP fetch aborted.\n", sizeof(msgbuf));
-	write(fileno(ttyout), msgbuf, len);
+	if (fromatty) {
+		len = snprintf(msgbuf, sizeof(msgbuf),
+		    "\n%s: HTTP fetch aborted.\n", getprogname());
+		if (len > 0)
+			write(fileno(ttyout), msgbuf, len);
+	}
+	siglongjmp(httpabort, 1);
+}
+
+static void
+timeouthttp(int notused)
+{
+	char msgbuf[100];
+	int len;
+
+	alarmtimer(0);
+	if (fromatty) {
+		len = snprintf(msgbuf, sizeof(msgbuf),
+		    "\n%s: HTTP fetch timeout.\n", getprogname());
+		if (len > 0)
+			write(fileno(ttyout), msgbuf, len);
+	}
 	siglongjmp(httpabort, 1);
 }
 
@@ -1687,6 +1783,7 @@ static int
 go_fetch(const char *url)
 {
 	char *proxyenv;
+	char *p;
 
 #ifndef NO_ABOUT
 	/*
@@ -1727,10 +1824,26 @@ go_fetch(const char *url)
 	/*
 	 * Check for file:// and http:// URLs.
 	 */
-	if (STRNEQUAL(url, HTTP_URL) || STRNEQUAL(url, FILE_URL))
+	if (STRNEQUAL(url, HTTP_URL)
+#ifdef WITH_SSL
+	    || STRNEQUAL(url, HTTPS_URL)
+#endif
+	    || STRNEQUAL(url, FILE_URL))
 		return (fetch_url(url, NULL, NULL, NULL));
 
 	/*
+	 * If it contains "://" but does not begin with ftp://
+	 * or something that was already handled, then it's
+	 * unsupported.
+	 *
+	 * If it contains ":" but not "://" then we assume the
+	 * part before the colon is a host name, not an URL scheme,
+	 * so we don't try to match that here.
+	 */
+	if ((p = strstr(url, "://")) != NULL && ! STRNEQUAL(url, FTP_URL))
+		errx(1, "Unsupported URL scheme `%.*s'", (int)(p - url), url);
+
+	/*
 	 * Try FTP URL-style and host:file arguments next.
 	 * If ftpproxy is set with an FTP URL, use fetch_url()
 	 * Othewise, use fetch_ftp().

Index: src/usr.bin/ftp/ftp.1
diff -u src/usr.bin/ftp/ftp.1:1.131 src/usr.bin/ftp/ftp.1:1.131.8.1
--- src/usr.bin/ftp/ftp.1:1.131	Fri Mar  5 07:41:10 2010
+++ src/usr.bin/ftp/ftp.1	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-.\" 	$NetBSD: ftp.1,v 1.131 2010/03/05 07:41:10 lukem Exp $
+.\" 	$NetBSD: ftp.1,v 1.131.8.1 2013/12/17 21:07:59 bouyer Exp $
 .\"
 .\" Copyright (c) 1996-2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -57,7 +57,7 @@
 .\"
 .\"	@(#)ftp.1	8.3 (Berkeley) 10/9/94
 .\"
-.Dd March 5, 2010
+.Dd December 22, 2012
 .Dt FTP 1
 .Os
 .Sh NAME
@@ -66,21 +66,11 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl 46AadefginpRtVv
-.Bk -words
 .Op Fl N Ar netrc
-.Ek
-.Bk -words
 .Op Fl o Ar output
-.Ek
-.Bk -words
 .Op Fl P Ar port
-.Ek
-.Bk -words
 .Op Fl q Ar quittime
-.Ek
-.Bk -words
 .Op Fl r Ar retry
-.Ek
 .Op Fl s Ar srcaddr
 .Bk -words
 .\" [-T dir,max[,inc]]
@@ -1335,7 +1325,7 @@ and
 .Ar value
 are not given, display all of the options and their values.
 The currently supported options are:
-.Bl -tag -width "http_proxy" -offset indent
+.Bl -tag -width "https_proxy" -offset indent
 .It Cm anonpass
 Defaults to
 .Ev $FTPANONPASS
@@ -1345,6 +1335,9 @@ Defaults to
 .It Cm http_proxy
 Defaults to
 .Ev $http_proxy .
+.It Cm https_proxy
+Defaults to
+.Ev $https_proxy .
 .It Cm no_proxy
 Defaults to
 .Ev $no_proxy .
@@ -1752,6 +1745,29 @@ and
 (and optionally
 .Sq password )
 is in the URL, use them for the first attempt to authenticate.
+.\" https://[user[:password]@]host[:port]/path
+.It Li https:// Ns Oo Ar user Ns Oo Li \&: Ns Ar password Oc Ns Li \&@ Oc \
+Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path
+An
+.Tn HTTPS
+URL, retrieved using the
+.Tn HTTPS
+protocol.
+If
+.Ic "set https_proxy"
+is defined, it is used as a URL to an
+.Tn HTTPS
+proxy server.
+If
+.Tn HTTPS
+authorization is required to retrieve
+.Ar path ,
+and
+.Sq user
+(and optionally
+.Sq password )
+is in the URL, use them for the first attempt to authenticate.
+There is currently no certificate validation and verification.
 .\" file:///path
 .It Li file:/// Ns Ar path
 A local URL, copied from
@@ -1901,7 +1917,7 @@ Failing the above checks, if
 .Dq globbing
 is enabled, local file names are expanded according to the rules
 used in the
-.Xr csh  1  ;
+.Xr csh 1 ;
 see the
 .Ic glob
 command.

Index: src/usr.bin/ftp/ftp.c
diff -u src/usr.bin/ftp/ftp.c:1.163 src/usr.bin/ftp/ftp.c:1.163.2.1
--- src/usr.bin/ftp/ftp.c:1.163	Sat Dec 10 05:53:58 2011
+++ src/usr.bin/ftp/ftp.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ftp.c,v 1.163 2011/12/10 05:53:58 lukem Exp $	*/
+/*	$NetBSD: ftp.c,v 1.163.2.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -92,7 +92,7 @@
 #if 0
 static char sccsid[] = "@(#)ftp.c	8.6 (Berkeley) 10/27/94";
 #else
-__RCSID("$NetBSD: ftp.c,v 1.163 2011/12/10 05:53:58 lukem Exp $");
+__RCSID("$NetBSD: ftp.c,v 1.163.2.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif
 #endif /* not lint */
 
@@ -208,7 +208,8 @@ hookup(const char *host, const char *por
 			    hname, sname);
 			continue;
 		}
-		if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+		if (ftp_connect(s, res->ai_addr, res->ai_addrlen,
+		    verbose || !res->ai_next) < 0) {
 			close(s);
 			s = -1;
 			continue;
@@ -1468,7 +1469,7 @@ initconn(void)
 			goto bad;
 
 		if (ftp_connect(data, (struct sockaddr *)&data_addr.si_su,
-		    data_addr.su_len) < 0) {
+		    data_addr.su_len, 1) < 0) {
 			if (activefallback) {
 				(void)close(data);
 				data = -1;

Index: src/usr.bin/ftp/ftp_var.h
diff -u src/usr.bin/ftp/ftp_var.h:1.81 src/usr.bin/ftp/ftp_var.h:1.81.8.1
--- src/usr.bin/ftp/ftp_var.h:1.81	Sun Apr 12 10:18:52 2009
+++ src/usr.bin/ftp/ftp_var.h	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: ftp_var.h,v 1.81 2009/04/12 10:18:52 lukem Exp $	*/
+/*	$NetBSD: ftp_var.h,v 1.81.8.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -177,6 +177,7 @@ enum {
 
 #define	FTP_PORT	21	/* default if ! getservbyname("ftp/tcp") */
 #define	HTTP_PORT	80	/* default if ! getservbyname("http/tcp") */
+#define	HTTPS_PORT	443	/* default if ! getservbyname("https/tcp") */
 #ifndef	GATE_PORT
 #define	GATE_PORT	21	/* default if ! getservbyname("ftpgate/tcp") */
 #endif
@@ -273,6 +274,9 @@ GLOBAL	char   *username;	/* name of user
 GLOBAL	sa_family_t family;	/* address family to use for connections */
 GLOBAL	const char *ftpport;	/* port number to use for FTP connections */
 GLOBAL	const char *httpport;	/* port number to use for HTTP connections */
+#ifdef WITH_SSL
+GLOBAL	const char *httpsport;	/* port number to use for HTTPS connections */
+#endif
 GLOBAL	const char *gateport;	/* port number to use for gateftp connections */
 GLOBAL	struct addrinfo *bindai; /* local address to bind as */
 

Index: src/usr.bin/ftp/main.c
diff -u src/usr.bin/ftp/main.c:1.120 src/usr.bin/ftp/main.c:1.120.2.1
--- src/usr.bin/ftp/main.c:1.120	Sat Dec 10 05:53:58 2011
+++ src/usr.bin/ftp/main.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.120 2011/12/10 05:53:58 lukem Exp $	*/
+/*	$NetBSD: main.c,v 1.120.2.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
@@ -98,7 +98,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 19
 #if 0
 static char sccsid[] = "@(#)main.c	8.6 (Berkeley) 10/9/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.120 2011/12/10 05:53:58 lukem Exp $");
+__RCSID("$NetBSD: main.c,v 1.120.2.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif
 #endif /* not lint */
 
@@ -126,6 +126,7 @@ __RCSID("$NetBSD: main.c,v 1.120 2011/12
 
 #define	FTP_PROXY	"ftp_proxy"	/* env var with FTP proxy location */
 #define	HTTP_PROXY	"http_proxy"	/* env var with HTTP proxy location */
+#define	HTTPS_PROXY	"https_proxy"	/* env var with HTTPS proxy location */
 #define	NO_PROXY	"no_proxy"	/* env var with list of non-proxied
 					 * hosts, comma or space separated */
 
@@ -150,6 +151,9 @@ main(int volatile argc, char **volatile 
 
 	ftpport = "ftp";
 	httpport = "http";
+#ifdef WITH_SSL
+	httpsport = "https";
+#endif
 	gateport = NULL;
 	cp = getenv("FTPSERVERPORT");
 	if (cp != NULL)
@@ -485,6 +489,7 @@ main(int volatile argc, char **volatile 
 	setupoption("anonpass",		getenv("FTPANONPASS"),	anonpass);
 	setupoption("ftp_proxy",	getenv(FTP_PROXY),	"");
 	setupoption("http_proxy",	getenv(HTTP_PROXY),	"");
+	setupoption("https_proxy",	getenv(HTTPS_PROXY),	"");
 	setupoption("no_proxy",		getenv(NO_PROXY),	"");
 	setupoption("pager",		getenv("PAGER"),	DEFAULTPAGER);
 	setupoption("prompt",		getenv("FTPPROMPT"),	DEFAULTPROMPT);
@@ -1044,6 +1049,9 @@ usage(void)
 "           [[user@]host [port]] [host:path[/]] [file:///file]\n"
 "           [ftp://[user[:pass]@]host[:port]/path[/]]\n";
 "           [http://[user[:pass]@]host[:port]/path] [...]\n"
+#ifdef WITH_SSL
+"           [https://[user[:pass]@]host[:port]/path] [...]\n"
+#endif
 "       %s -u URL file [...]\n", progname, progname);
 	exit(1);
 }

Index: src/usr.bin/ftp/progressbar.c
diff -u src/usr.bin/ftp/progressbar.c:1.21 src/usr.bin/ftp/progressbar.c:1.21.8.1
--- src/usr.bin/ftp/progressbar.c:1.21	Sun Apr 12 10:18:52 2009
+++ src/usr.bin/ftp/progressbar.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp $	*/
+/*	$NetBSD: progressbar.c,v 1.21.8.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -31,14 +31,15 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp $");
+__RCSID("$NetBSD: progressbar.c,v 1.21.8.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif /* not lint */
 
 /*
  * FTP User Program -- Misc support routines
  */
-#include <sys/types.h>
 #include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
 
 #include <err.h>
 #include <errno.h>

Index: src/usr.bin/ftp/util.c
diff -u src/usr.bin/ftp/util.c:1.156 src/usr.bin/ftp/util.c:1.156.2.1
--- src/usr.bin/ftp/util.c:1.156	Sat Dec 10 05:53:58 2011
+++ src/usr.bin/ftp/util.c	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: util.c,v 1.156 2011/12/10 05:53:58 lukem Exp $	*/
+/*	$NetBSD: util.c,v 1.156.2.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: util.c,v 1.156 2011/12/10 05:53:58 lukem Exp $");
+__RCSID("$NetBSD: util.c,v 1.156.2.1 2013/12/17 21:07:59 bouyer Exp $");
 #endif /* not lint */
 
 /*
@@ -202,25 +202,20 @@ getremoteinfo(void)
 			/* determine remote system type */
 	if (command("SYST") == COMPLETE) {
 		if (overbose) {
-			char *cp, c;
-
-			c = 0;
-			cp = strchr(reply_string + 4, ' ');
-			if (cp == NULL)
-				cp = strchr(reply_string + 4, '\r');
-			if (cp) {
-				if (cp[-1] == '.')
-					cp--;
-				c = *cp;
-				*cp = '\0';
-			}
-
-			fprintf(ttyout, "Remote system type is %s.\n",
-			    reply_string + 4);
-			if (cp)
-				*cp = c;
+			int os_len = strcspn(reply_string + 4, " \r\n\t");
+			if (os_len > 1 && reply_string[4 + os_len - 1] == '.')
+				os_len--;
+			fprintf(ttyout, "Remote system type is %.*s.\n",
+			    os_len, reply_string + 4);
 		}
-		if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
+		/*
+		 * Decide whether we should default to bninary.
+		 * Traditionally checked for "215 UNIX Type: L8", but
+		 * some printers report "Linux" ! so be more forgiving.
+		 * In reality we probably almost never want text any more.
+		 */
+		if (!strncasecmp(reply_string + 4, "unix", 4) ||
+		    !strncasecmp(reply_string + 4, "linux", 5)) {
 			if (proxy)
 				unix_proxy = 1;
 			else
@@ -1351,7 +1346,7 @@ get_line(FILE *stream, char *buf, size_t
  * error message displayed.)
  */
 int
-ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen)
+ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen, int pe)
 {
 	int		flags, rv, timeout, error;
 	socklen_t	slen;
@@ -1417,8 +1412,9 @@ ftp_connect(int sock, const struct socka
 	rv = connect(sock, name, namelen);	/* inititate the connection */
 	if (rv == -1) {				/* connection error */
 		if (errno != EINPROGRESS) {	/* error isn't "please wait" */
+			if (pe || (errno != EHOSTUNREACH))
  connecterror:
-			warn("Can't connect to `%s:%s'", hname, sname);
+				warn("Can't connect to `%s:%s'", hname, sname);
 			return -1;
 		}
 

Index: src/usr.bin/ftp/version.h
diff -u src/usr.bin/ftp/version.h:1.82 src/usr.bin/ftp/version.h:1.82.8.1
--- src/usr.bin/ftp/version.h:1.82	Sat Jun  5 13:59:39 2010
+++ src/usr.bin/ftp/version.h	Tue Dec 17 21:07:59 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: version.h,v 1.82 2010/06/05 13:59:39 lukem Exp $	*/
+/*	$NetBSD: version.h,v 1.82.8.1 2013/12/17 21:07:59 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
@@ -34,5 +34,5 @@
 #endif
 
 #ifndef FTP_VERSION
-#define	FTP_VERSION	"20100605"
+#define	FTP_VERSION	"20130220"
 #endif

Added files:

Index: src/usr.bin/ftp/ssl.c
diff -u /dev/null src/usr.bin/ftp/ssl.c:1.2.10.2
--- /dev/null	Tue Dec 17 21:07:59 2013
+++ src/usr.bin/ftp/ssl.c	Tue Dec 17 21:07:59 2013
@@ -0,0 +1,608 @@
+/*	$NetBSD: ssl.c,v 1.2.10.2 2013/12/17 21:07:59 bouyer Exp $	*/
+
+/*-
+ * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
+ * Copyright (c) 2008, 2010 Joerg Sonnenberger <jo...@netbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer
+ *    in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: ssl.c,v 1.2.10.2 2013/12/17 21:07:59 bouyer Exp $");
+#endif
+
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/param.h>
+#include <sys/select.h>
+#include <sys/uio.h>
+
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+#include <openssl/crypto.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+#include "ssl.h"
+
+extern int quit_time, verbose, ftp_debug;
+extern FILE *ttyout;
+
+struct fetch_connect {
+	int			 sd;		/* file/socket descriptor */
+	char			*buf;		/* buffer */
+	size_t			 bufsize;	/* buffer size */
+	size_t			 bufpos;	/* position of buffer */
+	size_t			 buflen;	/* length of buffer contents */
+	struct {				/* data cached after an
+						   interrupted read */
+		char	*buf;
+		size_t	 size;
+		size_t	 pos;
+		size_t	 len;
+	} cache;
+	int 			 issock;
+	int			 iserr;
+	int			 iseof;
+	SSL			*ssl;		/* SSL handle */
+};
+
+/*
+ * Write a vector to a connection w/ timeout
+ * Note: can modify the iovec.
+ */
+static ssize_t
+fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
+{
+	struct timeval now, timeout, delta;
+	fd_set writefds;
+	ssize_t len, total;
+	int r;
+
+	if (quit_time > 0) {
+		FD_ZERO(&writefds);
+		gettimeofday(&timeout, NULL);
+		timeout.tv_sec += quit_time;
+	}
+
+	total = 0;
+	while (iovcnt > 0) {
+		while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) {
+			FD_SET(conn->sd, &writefds);
+			gettimeofday(&now, NULL);
+			delta.tv_sec = timeout.tv_sec - now.tv_sec;
+			delta.tv_usec = timeout.tv_usec - now.tv_usec;
+			if (delta.tv_usec < 0) {
+				delta.tv_usec += 1000000;
+				delta.tv_sec--;
+			}
+			if (delta.tv_sec < 0) {
+				errno = ETIMEDOUT;
+				return -1;
+			}
+			errno = 0;
+			r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
+			if (r == -1) {
+				if (errno == EINTR)
+					continue;
+				return -1;
+			}
+		}
+		errno = 0;
+		if (conn->ssl != NULL)
+			len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
+		else
+			len = writev(conn->sd, iov, iovcnt);
+		if (len == 0) {
+			/* we consider a short write a failure */
+			/* XXX perhaps we shouldn't in the SSL case */
+			errno = EPIPE;
+			return -1;
+		}
+		if (len < 0) {
+			if (errno == EINTR)
+				continue;
+			return -1;
+		}
+		total += len;
+		while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
+			len -= iov->iov_len;
+			iov++;
+			iovcnt--;
+		}
+		if (iovcnt > 0) {
+			iov->iov_len -= len;
+			iov->iov_base = (char *)iov->iov_base + len;
+		}
+	}
+	return total;
+}
+
+/*
+ * Write to a connection w/ timeout
+ */
+static int
+fetch_write(struct fetch_connect *conn, const char *str, size_t len)
+{
+	struct iovec iov[1];
+
+	iov[0].iov_base = (char *)__UNCONST(str);
+	iov[0].iov_len = len;
+	return fetch_writev(conn, iov, 1);
+}
+
+/*
+ * Send a formatted line; optionally echo to terminal
+ */
+int
+fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
+{
+	va_list ap;
+	size_t len;
+	char *msg;
+	int r;
+
+	va_start(ap, fmt);
+	len = vasprintf(&msg, fmt, ap);
+	va_end(ap);
+
+	if (msg == NULL) {
+		errno = ENOMEM;
+		return -1;
+	}
+
+	r = fetch_write(conn, msg, len);
+	free(msg);
+	return r;
+}
+
+int
+fetch_fileno(struct fetch_connect *conn)
+{
+
+	return conn->sd;
+}
+
+int
+fetch_error(struct fetch_connect *conn)
+{
+
+	return conn->iserr;
+}
+
+static void
+fetch_clearerr(struct fetch_connect *conn)
+{
+
+	conn->iserr = 0;
+}
+
+int
+fetch_flush(struct fetch_connect *conn)
+{
+	int v;
+
+	if (conn->issock) {
+#ifdef TCP_NOPUSH
+		v = 0;
+		setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
+#endif
+		v = 1;
+		setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
+	}
+	return 0;
+}
+
+/*ARGSUSED*/
+struct fetch_connect *
+fetch_open(const char *fname, const char *fmode)
+{
+	struct fetch_connect *conn;
+	int fd;
+
+	fd = open(fname, O_RDONLY); /* XXX: fmode */
+	if (fd < 0)
+		return NULL;
+
+	if ((conn = calloc(1, sizeof(*conn))) == NULL) {
+		close(fd);
+		return NULL;
+	}
+
+	conn->sd = fd;
+	conn->issock = 0;
+	return conn;
+}
+
+/*ARGSUSED*/
+struct fetch_connect *
+fetch_fdopen(int sd, const char *fmode)
+{
+	struct fetch_connect *conn;
+#if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH)
+	int opt = 1;
+#endif
+
+	if ((conn = calloc(1, sizeof(*conn))) == NULL)
+		return NULL;
+
+	conn->sd = sd;
+	conn->issock = 1;
+	fcntl(sd, F_SETFD, FD_CLOEXEC);
+#ifdef SO_NOSIGPIPE
+	setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
+#endif
+#ifdef TCP_NOPUSH
+	setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
+#endif
+	return conn;
+}
+
+int
+fetch_close(struct fetch_connect *conn)
+{
+	int rv = 0;
+
+	if (conn != NULL) {
+		fetch_flush(conn);
+		SSL_free(conn->ssl);
+		rv = close(conn->sd);
+		if (rv < 0) {
+			errno = rv;
+			rv = EOF;
+		}
+		free(conn->cache.buf);
+		free(conn->buf);
+		free(conn);
+	}
+	return rv;
+}
+
+#define FETCH_READ_WAIT		-2
+#define FETCH_READ_ERROR	-1
+
+static ssize_t
+fetch_ssl_read(SSL *ssl, void *buf, size_t len)
+{
+	ssize_t rlen;
+	int ssl_err;
+
+	rlen = SSL_read(ssl, buf, len);
+	if (rlen < 0) {
+		ssl_err = SSL_get_error(ssl, rlen);
+		if (ssl_err == SSL_ERROR_WANT_READ ||
+		    ssl_err == SSL_ERROR_WANT_WRITE) {
+			return FETCH_READ_WAIT;
+		}
+		ERR_print_errors_fp(ttyout);
+		return FETCH_READ_ERROR;
+	}
+	return rlen;
+}
+
+static ssize_t
+fetch_nonssl_read(int sd, void *buf, size_t len)
+{
+	ssize_t rlen;
+
+	rlen = read(sd, buf, len);
+	if (rlen < 0) {
+		if (errno == EAGAIN || errno == EINTR)
+			return FETCH_READ_WAIT;
+		return FETCH_READ_ERROR;
+	}
+	return rlen;
+}
+
+/*
+ * Cache some data that was read from a socket but cannot be immediately
+ * returned because of an interrupted system call.
+ */
+static int
+fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
+{
+
+	if (conn->cache.size < nbytes) {
+		char *tmp = realloc(conn->cache.buf, nbytes);
+		if (tmp == NULL)
+			return -1;
+
+		conn->cache.buf = tmp;
+		conn->cache.size = nbytes;
+	}
+
+	memcpy(conn->cache.buf, src, nbytes);
+	conn->cache.len = nbytes;
+	conn->cache.pos = 0;
+	return 0;
+}
+
+ssize_t
+fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
+{
+	struct timeval now, timeout, delta;
+	fd_set readfds;
+	ssize_t rlen, total;
+	size_t len;
+	char *start, *buf;
+
+	if (quit_time > 0) {
+		gettimeofday(&timeout, NULL);
+		timeout.tv_sec += quit_time;
+	}
+
+	total = 0;
+	start = buf = ptr;
+	len = size * nmemb;
+
+	if (conn->cache.len > 0) {
+		/*
+		 * The last invocation of fetch_read was interrupted by a
+		 * signal after some data had been read from the socket. Copy
+		 * the cached data into the supplied buffer before trying to
+		 * read from the socket again.
+		 */
+		total = (conn->cache.len < len) ? conn->cache.len : len;
+		memcpy(buf, conn->cache.buf, total);
+
+		conn->cache.len -= total;
+		conn->cache.pos += total;
+		len -= total;
+		buf += total;
+	}
+
+	while (len > 0) {
+		/*
+		 * The socket is non-blocking.  Instead of the canonical
+		 * select() -> read(), we do the following:
+		 *
+		 * 1) call read() or SSL_read().
+		 * 2) if an error occurred, return -1.
+		 * 3) if we received data but we still expect more,
+		 *    update our counters and loop.
+		 * 4) if read() or SSL_read() signaled EOF, return.
+		 * 5) if we did not receive any data but we're not at EOF,
+		 *    call select().
+		 *
+		 * In the SSL case, this is necessary because if we
+		 * receive a close notification, we have to call
+		 * SSL_read() one additional time after we've read
+		 * everything we received.
+		 *
+		 * In the non-SSL case, it may improve performance (very
+		 * slightly) when reading small amounts of data.
+		 */
+		if (conn->ssl != NULL)
+			rlen = fetch_ssl_read(conn->ssl, buf, len);
+		else
+			rlen = fetch_nonssl_read(conn->sd, buf, len);
+		if (rlen == 0) {
+			break;
+		} else if (rlen > 0) {
+			len -= rlen;
+			buf += rlen;
+			total += rlen;
+			continue;
+		} else if (rlen == FETCH_READ_ERROR) {
+			if (errno == EINTR)
+				fetch_cache_data(conn, start, total);
+			return -1;
+		}
+		FD_ZERO(&readfds);
+		while (!FD_ISSET(conn->sd, &readfds)) {
+			FD_SET(conn->sd, &readfds);
+			if (quit_time > 0) {
+				gettimeofday(&now, NULL);
+				if (!timercmp(&timeout, &now, >)) {
+					errno = ETIMEDOUT;
+					return -1;
+				}
+				timersub(&timeout, &now, &delta);
+			}
+			errno = 0;
+			if (select(conn->sd + 1, &readfds, NULL, NULL,
+				quit_time > 0 ? &delta : NULL) < 0) {
+				if (errno == EINTR)
+					continue;
+				return -1;
+			}
+		}
+	}
+	return total;
+}
+
+#define MIN_BUF_SIZE 1024
+
+/*
+ * Read a line of text from a connection w/ timeout
+ */
+char *
+fetch_getln(char *str, int size, struct fetch_connect *conn)
+{
+	size_t tmpsize;
+	ssize_t len;
+	char c;
+
+	if (conn->buf == NULL) {
+		if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
+			errno = ENOMEM;
+			conn->iserr = 1;
+			return NULL;
+		}
+		conn->bufsize = MIN_BUF_SIZE;
+	}
+
+	if (conn->iserr || conn->iseof)
+		return NULL;
+
+	if (conn->buflen - conn->bufpos > 0)
+		goto done;
+
+	conn->buf[0] = '\0';
+	conn->bufpos = 0;
+	conn->buflen = 0;
+	do {
+		len = fetch_read(&c, sizeof(c), 1, conn);
+		if (len == -1) {
+			conn->iserr = 1;
+			return NULL;
+		}
+		if (len == 0) {
+			conn->iseof = 1;
+			break;
+		}
+		conn->buf[conn->buflen++] = c;
+		if (conn->buflen == conn->bufsize) {
+			char *tmp = conn->buf;
+			tmpsize = conn->bufsize * 2 + 1;
+			if ((tmp = realloc(tmp, tmpsize)) == NULL) {
+				errno = ENOMEM;
+				conn->iserr = 1;
+				return NULL;
+			}
+			conn->buf = tmp;
+			conn->bufsize = tmpsize;
+		}
+	} while (c != '\n');
+
+	if (conn->buflen == 0)
+		return NULL;
+ done:
+	tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos));
+	memcpy(str, conn->buf + conn->bufpos, tmpsize);
+	str[tmpsize] = '\0';
+	conn->bufpos += tmpsize;
+	return str;
+}
+
+int
+fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
+    const char **errormsg)
+{
+	size_t len;
+	int rv;
+
+	if (fetch_getln(buf, buflen, conn) == NULL) {
+		if (conn->iseof) {	/* EOF */
+			rv = -2;
+			if (errormsg)
+				*errormsg = "\nEOF received";
+		} else {		/* error */
+			rv = -1;
+			if (errormsg)
+				*errormsg = "Error encountered";
+		}
+		fetch_clearerr(conn);
+		return rv;
+	}
+	len = strlen(buf);
+	if (buf[len - 1] == '\n') {	/* clear any trailing newline */
+		buf[--len] = '\0';
+	} else if (len == buflen - 1) {	/* line too long */
+		while (1) {
+			char c;
+			ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn);
+			if (rlen <= 0 || c == '\n')
+				break;
+		}
+		if (errormsg)
+			*errormsg = "Input line is too long";
+		fetch_clearerr(conn);
+		return -3;
+	}
+	if (errormsg)
+		*errormsg = NULL;
+	return len;
+}
+
+void *
+fetch_start_ssl(int sock)
+{
+	SSL *ssl;
+	SSL_CTX *ctx;
+	int ret, ssl_err;
+
+	/* Init the SSL library and context */
+	if (!SSL_library_init()){
+		fprintf(ttyout, "SSL library init failed\n");
+		return NULL;
+	}
+
+	SSL_load_error_strings();
+
+	ctx = SSL_CTX_new(SSLv23_client_method());
+	SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
+
+	ssl = SSL_new(ctx);
+	if (ssl == NULL){
+		fprintf(ttyout, "SSL context creation failed\n");
+		SSL_CTX_free(ctx);
+		return NULL;
+	}
+	SSL_set_fd(ssl, sock);
+	while ((ret = SSL_connect(ssl)) == -1) {
+		ssl_err = SSL_get_error(ssl, ret);
+		if (ssl_err != SSL_ERROR_WANT_READ &&
+		    ssl_err != SSL_ERROR_WANT_WRITE) {
+			ERR_print_errors_fp(ttyout);
+			SSL_free(ssl);
+			return NULL;
+		}
+	}
+
+	if (ftp_debug && verbose) {
+		X509 *cert;
+		X509_NAME *name;
+		char *str;
+
+		fprintf(ttyout, "SSL connection established using %s\n",
+		    SSL_get_cipher(ssl));
+		cert = SSL_get_peer_certificate(ssl);
+		name = X509_get_subject_name(cert);
+		str = X509_NAME_oneline(name, 0, 0);
+		fprintf(ttyout, "Certificate subject: %s\n", str);
+		free(str);
+		name = X509_get_issuer_name(cert);
+		str = X509_NAME_oneline(name, 0, 0);
+		fprintf(ttyout, "Certificate issuer: %s\n", str);
+		free(str);
+	}
+
+	return ssl;
+}
+
+
+void
+fetch_set_ssl(struct fetch_connect *conn, void *ssl)
+{
+	conn->ssl = ssl;
+}

Index: src/usr.bin/ftp/ssl.h
diff -u /dev/null src/usr.bin/ftp/ssl.h:1.1.10.2
--- /dev/null	Tue Dec 17 21:07:59 2013
+++ src/usr.bin/ftp/ssl.h	Tue Dec 17 21:07:59 2013
@@ -0,0 +1,62 @@
+/*	$NetBSD: ssl.h,v 1.1.10.2 2013/12/17 21:07:59 bouyer Exp $	*/
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifdef WITH_SSL
+
+#define FETCH struct fetch_connect
+struct fetch_connect;
+
+int fetch_printf(struct fetch_connect *, const char *fmt, ...);
+int fetch_fileno(struct fetch_connect *);
+int fetch_error(struct fetch_connect *);
+int fetch_flush(struct fetch_connect *);
+struct fetch_connect *fetch_open(const char *, const char *);
+struct fetch_connect *fetch_fdopen(int, const char *);
+int fetch_close(struct fetch_connect *);
+ssize_t fetch_read(void *, size_t, size_t, struct fetch_connect *);
+char *fetch_getln(char *, int, struct fetch_connect *);
+int fetch_getline(struct fetch_connect *, char *, size_t, const char **);
+void fetch_set_ssl(struct fetch_connect *, void *);
+void *fetch_start_ssl(int);
+
+#else	/* !WITH_SSL */
+
+#define FETCH FILE
+
+#define	fetch_printf	fprintf
+#define	fetch_fileno	fileno
+#define	fetch_error	ferror
+#define	fetch_flush	fflush
+#define	fetch_open	fopen
+#define	fetch_fdopen	fdopen
+#define	fetch_close	fclose
+#define	fetch_read	fread
+#define	fetch_getln	fgets
+#define	fetch_getline	get_line
+#define	fetch_set_ssl(a, b)
+
+#endif	/* !WITH_SSL */

Reply via email to