From 0511850fc031060430557667860d15d8fb599d19 Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sat, 21 Apr 2007 20:18:21 +0000 Subject: [PATCH] Sync with NetBSD. In addition to some bug fixes, this brings in -s srcaddr functionality -- using srcaddr as the local IP address for the connection. --- contrib/tnftp/cmds.c | 93 ++++++++------ contrib/tnftp/cmdtab.c | 6 +- contrib/tnftp/complete.c | 7 +- contrib/tnftp/extern.h | 6 +- contrib/tnftp/fetch.c | 93 +++++++------- contrib/tnftp/ftp.1 | 23 ++-- contrib/tnftp/ftp.c | 240 ++++++++++++++++++------------------ contrib/tnftp/ftp_var.h | 7 +- contrib/tnftp/main.c | 66 ++++++---- contrib/tnftp/progressbar.c | 52 +++++--- contrib/tnftp/ruserpass.c | 63 +++++++--- contrib/tnftp/util.c | 113 ++++++++++++----- contrib/tnftp/version.h | 6 +- 13 files changed, 447 insertions(+), 328 deletions(-) diff --git a/contrib/tnftp/cmds.c b/contrib/tnftp/cmds.c index 10bebeee47..554b17ade2 100644 --- a/contrib/tnftp/cmds.c +++ b/contrib/tnftp/cmds.c @@ -1,7 +1,7 @@ -/* $NetBSD: cmds.c,v 1.118 2006/01/31 20:05:35 christos Exp $ */ +/* $NetBSD: cmds.c,v 1.121 2007/04/18 01:39:04 lukem Exp $ */ /*- - * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1996-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -103,7 +103,7 @@ #if 0 static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94"; #else -__RCSID("$NetBSD: cmds.c,v 1.118 2006/01/31 20:05:35 christos Exp $"); +__RCSID("$NetBSD: cmds.c,v 1.121 2007/04/18 01:39:04 lukem Exp $"); #endif #endif /* not lint */ @@ -131,7 +131,7 @@ __RCSID("$NetBSD: cmds.c,v 1.118 2006/01/31 20:05:35 christos Exp $"); #include "ftp_var.h" #include "version.h" -struct types { +static struct types { char *t_name; char *t_mode; int t_type; @@ -145,30 +145,43 @@ struct types { { NULL } }; -sigjmp_buf jabort; -const char *mname; +static sigjmp_buf jabort; static int confirm(const char *, const char *); +static void mintr(int); +static void mabort(const char *); static const char *doprocess(char *, size_t, const char *, int, int, int); static const char *domap(char *, size_t, const char *); static const char *docase(char *, size_t, const char *); static const char *dotrans(char *, size_t, const char *); +/* + * Confirm if "cmd" is to be performed upon "file". + * If "file" is NULL, generate a "Continue with" prompt instead. + */ static int confirm(const char *cmd, const char *file) { const char *errormsg; char line[BUFSIZ]; + const char *promptleft, *promptright; if (!interactive || confirmrest) return (1); + if (file == NULL) { + promptleft = "Continue with"; + promptright = cmd; + } else { + promptleft = cmd; + promptright = file; + } while (1) { - fprintf(ttyout, "%s %s [anpqy?]? ", cmd, file); + fprintf(ttyout, "%s %s [anpqy?]? ", promptleft, promptright); (void)fflush(ttyout); if (getline(stdin, line, sizeof(line), &errormsg) < 0) { mflag = 0; - fprintf(ttyout, "%s; %s aborted\n", errormsg, mname); + fprintf(ttyout, "%s; %s aborted\n", errormsg, cmd); return (0); } switch (tolower((unsigned char)*line)) { @@ -183,7 +196,7 @@ confirm(const char *cmd, const char *file) break; case 'q': mflag = 0; - fprintf(ttyout, "%s aborted.\n", mname); + fprintf(ttyout, "%s aborted.\n", cmd); /* FALLTHROUGH */ case 'n': return (0); @@ -270,8 +283,7 @@ changetype(int newtype, int show) if (newtype == p->t_type) break; if (p->t_name == 0) { - warnx("internal error: unknown type %d.", newtype); - return; + errx(1, "changetype: unknown type %d", newtype); } if (newtype == TYPE_L && bytename[0] != '\0') comret = command("TYPE %s %s", p->t_mode, bytename); @@ -459,11 +471,10 @@ mput(int argc, char *argv[]) code = -1; return; } - mname = argv[0]; mflag = 1; oldintr = xsignal(SIGINT, mintr); if (sigsetjmp(jabort, 1)) - mabort(); + mabort(argv[0]); if (proxy) { char *cp; @@ -481,7 +492,7 @@ mput(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", "mput")) { + if (confirm(argv[0], NULL)) { mflag++; } interactive = ointer; @@ -505,7 +516,7 @@ mput(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", "mput")) { + if (confirm(argv[0], NULL)) { mflag++; } interactive = ointer; @@ -517,7 +528,7 @@ mput(int argc, char *argv[]) memset(&gl, 0, sizeof(gl)); flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { - warnx("%s: not found", argv[i]); + warnx("Glob pattern `%s' not found", argv[i]); globfree(&gl); continue; } @@ -533,7 +544,7 @@ mput(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", "mput")) { + if (confirm(argv[0], NULL)) { mflag++; } interactive = ointer; @@ -607,7 +618,7 @@ getit(int argc, char *argv[], int restartit, const char *mode) ret = stat(locfile, &stbuf); if (restartit == 1) { if (ret < 0) { - warn("local: %s", locfile); + warn("Can't stat `%s'", locfile); goto freegetit; } restart_point = stbuf.st_size; @@ -635,7 +646,7 @@ getit(int argc, char *argv[], int restartit, const char *mode) } /* ARGSUSED */ -void +static void mintr(int signo) { @@ -645,8 +656,8 @@ mintr(int signo) siglongjmp(jabort, 1); } -void -mabort(void) +static void +mabort(const char *cmd) { int ointer, oconf; @@ -655,7 +666,7 @@ mabort(void) oconf = confirmrest; interactive = 1; confirmrest = 0; - if (confirm("Continue with", mname)) { + if (confirm(cmd, NULL)) { interactive = ointer; confirmrest = oconf; return; @@ -684,7 +695,6 @@ mget(int argc, char *argv[]) code = -1; return; } - mname = argv[0]; mflag = 1; restart_point = 0; restartit = 0; @@ -698,7 +708,7 @@ mget(int argc, char *argv[]) } oldintr = xsignal(SIGINT, mintr); if (sigsetjmp(jabort, 1)) - mabort(); + mabort(argv[0]); while ((cp = remglob(argv, proxy, NULL)) != NULL) { char buf[MAXPATHLEN]; if (*cp == '\0' || !connected) { @@ -721,7 +731,7 @@ mget(int argc, char *argv[]) if (stat(tp, &stbuf) == 0) restart_point = stbuf.st_size; else - warn("stat %s", tp); + warn("Can't stat `%s'", tp); } recvrequest("RETR", tp, cp, restart_point ? "r+" : "w", tp != cp || !interactive, 1); @@ -729,7 +739,7 @@ mget(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", "mget")) + if (confirm(argv[0], NULL)) mflag++; interactive = ointer; } @@ -755,7 +765,7 @@ fget(int argc, char *argv[]) fp = fopen(argv[1], "r"); if (fp == NULL) { - fprintf(ttyout, "Cannot open source file %s\n", argv[1]); + fprintf(ttyout, "Can't open source file %s\n", argv[1]); code = -1; return; } @@ -1171,7 +1181,7 @@ lcd(int argc, char *argv[]) if ((locdir = globulize(argv[1])) == NULL) return; if (chdir(locdir) == -1) - warn("lcd %s", locdir); + warn("Can't chdir `%s'", locdir); else { updatelocalcwd(); if (localcwd[0]) { @@ -1217,11 +1227,10 @@ mdelete(int argc, char *argv[]) code = -1; return; } - mname = argv[0]; mflag = 1; oldintr = xsignal(SIGINT, mintr); if (sigsetjmp(jabort, 1)) - mabort(); + mabort(argv[0]); while ((cp = remglob(argv, 0, NULL)) != NULL) { if (*cp == '\0') { mflag = 0; @@ -1233,7 +1242,7 @@ mdelete(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", "mdelete")) { + if (confirm(argv[0], NULL)) { mflag++; } interactive = ointer; @@ -1337,7 +1346,6 @@ ls(int argc, char *argv[]) (void)strlcpy(locfile + 1, p, len - 1); freelocfile = 1; } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') { - mname = argv[0]; if ((locfile = globulize(locfile)) == NULL || !confirm("output to local-file:", locfile)) { code = -1; @@ -1374,7 +1382,6 @@ mls(int argc, char *argv[]) } odest = dest = argv[argc - 1]; argv[argc - 1] = NULL; - mname = argv[0]; if (strcmp(dest, "-") && *dest != '|') if (((dest = globulize(dest)) == NULL) || !confirm("output to local-file:", dest)) { @@ -1385,7 +1392,7 @@ mls(int argc, char *argv[]) mflag = 1; oldintr = xsignal(SIGINT, mintr); if (sigsetjmp(jabort, 1)) - mabort(); + mabort(argv[0]); for (i = 1; mflag && i < argc-1 && connected; i++) { mode = (i == 1) ? "w" : "a"; recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode, @@ -1393,7 +1400,7 @@ mls(int argc, char *argv[]) if (!mflag && fromatty) { ointer = interactive; interactive = 1; - if (confirm("Continue with", argv[0])) { + if (confirm(argv[0], NULL)) { mflag++; } interactive = ointer; @@ -1446,7 +1453,7 @@ shell(int argc, char *argv[]) else { execl(shell, shellnam, (char *)0); } - warn("%s", shell); + warn("Can't execute `%s'", shell); code = -1; exit(1); } @@ -1455,7 +1462,7 @@ shell(int argc, char *argv[]) ; (void)xsignal(SIGINT, oldintr); if (pid == -1) { - warn("Try again later"); + warn("Can't fork a subshell; try again later"); code = -1; } else code = 0; @@ -1468,6 +1475,7 @@ void user(int argc, char *argv[]) { char *password; + char emptypass[] = ""; int n, aflag = 0; if (argc == 0) @@ -1485,6 +1493,8 @@ user(int argc, char *argv[]) if (n == CONTINUE) { if (argc < 3) { password = getpass("Password: "); + if (password == NULL) + password = emptypass; } else { password = argv[2]; } @@ -1495,6 +1505,8 @@ user(int argc, char *argv[]) aflag++; if (argc < 4) { password = getpass("Account: "); + if (password == NULL) + password = emptypass; } else { password = argv[3]; } @@ -1782,6 +1794,7 @@ void account(int argc, char *argv[]) { char *ap; + char emptypass[] = ""; if (argc == 0 || argc > 2) { UPRINTF("usage: %s [password]\n", argv[0]); @@ -1790,9 +1803,13 @@ account(int argc, char *argv[]) } else if (argc == 2) ap = argv[1]; - else + else { ap = getpass("Account:"); + if (ap == NULL) + ap = emptypass; + } (void)command("ACCT %s", ap); + memset(ap, 0, strlen(ap)); } sigjmp_buf abortprox; diff --git a/contrib/tnftp/cmdtab.c b/contrib/tnftp/cmdtab.c index 6ebe22e365..8f80e1ca10 100644 --- a/contrib/tnftp/cmdtab.c +++ b/contrib/tnftp/cmdtab.c @@ -1,4 +1,4 @@ -/* $NetBSD: cmdtab.c,v 1.46 2006/01/31 20:05:36 christos Exp $ */ +/* $NetBSD: cmdtab.c,v 1.47 2007/04/11 04:40:19 lukem Exp $ */ /*- * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ #if 0 static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94"; #else -__RCSID("$NetBSD: cmdtab.c,v 1.46 2006/01/31 20:05:36 christos Exp $"); +__RCSID("$NetBSD: cmdtab.c,v 1.47 2007/04/11 04:40:19 lukem Exp $"); #endif #endif /* not lint */ @@ -206,7 +206,7 @@ struct cmd cmdtab[] = { { "chmod", H(chmodhelp), 0, 1, 1, CMPL(nr) do_chmod }, { "close", H(disconhelp), 0, 1, 1, CMPL0 disconnect }, { "cr", H(crhelp), 0, 0, 0, CMPL0 setcr }, - { "ftp_debug", H(debughelp), 0, 0, 0, CMPL0 setdebug }, + { "debug", H(debughelp), 0, 0, 0, CMPL0 setdebug }, { "delete", H(deletehelp), 0, 1, 1, CMPL(r) delete }, { "dir", H(lshelp), 1, 1, 1, CMPL(rl) ls }, { "disconnect", H(disconhelp), 0, 1, 1, CMPL0 disconnect }, diff --git a/contrib/tnftp/complete.c b/contrib/tnftp/complete.c index 0f593b3088..dae79199b1 100644 --- a/contrib/tnftp/complete.c +++ b/contrib/tnftp/complete.c @@ -1,4 +1,4 @@ -/* $NetBSD: complete.c,v 1.41 2006/01/31 20:01:23 christos Exp $ */ +/* $NetBSD: complete.c,v 1.42 2007/04/17 05:52:03 lukem Exp $ */ /*- * Copyright (c) 1997-2000,2005 The NetBSD Foundation, Inc. @@ -38,7 +38,7 @@ #include #ifndef lint -__RCSID("$NetBSD: complete.c,v 1.41 2006/01/31 20:01:23 christos Exp $"); +__RCSID("$NetBSD: complete.c,v 1.42 2007/04/17 05:52:03 lukem Exp $"); #endif /* not lint */ /* @@ -426,7 +426,8 @@ complete(EditLine *el, int ch) } return (complete_remote(word, dolist)); default: - errx(1, "unknown complete type `%c'", cmpltype); + errx(1, "complete: unknown complete type `%c'", + cmpltype); return (CC_ERROR); } /* NOTREACHED */ diff --git a/contrib/tnftp/extern.h b/contrib/tnftp/extern.h index 206fc29679..628384ccb9 100644 --- a/contrib/tnftp/extern.h +++ b/contrib/tnftp/extern.h @@ -1,7 +1,7 @@ -/* $NetBSD: extern.h,v 1.70 2006/01/31 20:01:23 christos Exp $ */ +/* $NetBSD: extern.h,v 1.71 2007/04/18 01:39:04 lukem Exp $ */ /*- - * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1996-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -160,13 +160,11 @@ void lostpeer(int); void lpage(int, char **); void lpwd(int, char **); void ls(int, char **); -void mabort(void); void macdef(int, char **); void makeargv(void); void makedir(int, char **); void mdelete(int, char **); void mget(int, char **); -void mintr(int); void mls(int, char **); void mlst(int, char **); void modtime(int, char **); diff --git a/contrib/tnftp/fetch.c b/contrib/tnftp/fetch.c index 922752f540..0b66024555 100644 --- a/contrib/tnftp/fetch.c +++ b/contrib/tnftp/fetch.c @@ -1,7 +1,7 @@ -/* $NetBSD: fetch.c,v 1.171 2006/09/22 22:29:25 elad Exp $ */ +/* $NetBSD: fetch.c,v 1.175 2007/04/17 05:52:03 lukem Exp $ */ /*- - * Copyright (c) 1997-2006 The NetBSD Foundation, Inc. + * Copyright (c) 1997-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -41,7 +41,7 @@ #include #ifndef lint -__RCSID("$NetBSD: fetch.c,v 1.171 2006/09/22 22:29:25 elad Exp $"); +__RCSID("$NetBSD: fetch.c,v 1.175 2007/04/17 05:52:03 lukem Exp $"); #endif /* not lint */ /* @@ -112,7 +112,7 @@ static int redirect_loop; * Determine if token is the next word in buf (case insensitive). * If so, advance buf past the token and any trailing LWS, and * return a pointer to the token (in buf). Otherwise, return NULL. - * token may be preceeded by LWS. + * token may be preceded by LWS. * token must be followed by LWS or NUL. (I.e, don't partial match). */ static const char * @@ -161,7 +161,7 @@ auth_url(const char *challenge, char **response, const char *guser, DPRINTF("auth_url: challenge `%s'\n", challenge); if (! match_token(&cp, scheme)) { - warnx("Unsupported authentication challenge - `%s'", + warnx("Unsupported authentication challenge `%s'", challenge); goto cleanup_auth_url; } @@ -170,7 +170,7 @@ auth_url(const char *challenge, char **response, const char *guser, if (STRNEQUAL(cp, REALM)) cp += sizeof(REALM) - 1; else { - warnx("Unsupported authentication challenge - `%s'", + warnx("Unsupported authentication challenge `%s'", challenge); goto cleanup_auth_url; } @@ -181,7 +181,7 @@ auth_url(const char *challenge, char **response, const char *guser, realm = (char *)ftp_malloc(len + 1); (void)strlcpy(realm, cp, len + 1); } else { - warnx("Unsupported authentication challenge - `%s'", + warnx("Unsupported authentication challenge `%s'", challenge); goto cleanup_auth_url; } @@ -199,8 +199,13 @@ auth_url(const char *challenge, char **response, const char *guser, } if (gpass != NULL) pass = (char *)gpass; - else + else { pass = getpass("Password: "); + if (pass == NULL) { + warnx("Can't read password"); + goto cleanup_auth_url; + } + } clen = strlen(user) + strlen(pass) + 2; /* user + ":" + pass + "\0" */ clear = (char *)ftp_malloc(clen); @@ -467,21 +472,31 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) struct addrinfo hints, *res, *res0 = NULL; int error; char hbuf[NI_MAXHOST]; - volatile sigfunc oldintr, oldintp; - volatile int s; + sigfunc volatile oldintr; + sigfunc volatile oldintp; + int volatile s; struct stat sb; - int ischunked, isproxy, rval, hcode; + int volatile ischunked; + int volatile isproxy; + int volatile rval; + int volatile hcode; size_t len; static size_t bufsize; static char *xferbuf; const char *cp, *token; - char *ep, *buf, *savefile; - char *auth, *location, *message; - char *user, *pass, *host, *port, *path, *decodedpath; + char *ep; + char *volatile buf; + char *volatile savefile; + char *volatile auth; + char *volatile location; + char *volatile message; + char *user, *pass, *host, *port, *path; + char *volatile decodedpath; char *puser, *ppass, *useragent; off_t hashbytes, rangestart, rangeend, entitylen; - int (*closefunc)(FILE *); - FILE *fin, *fout; + int (*volatile closefunc)(FILE *); + FILE *volatile fin; + FILE *volatile fout; time_t mtime; url_t urltype; in_port_t portnum; @@ -496,22 +511,6 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) rval = 1; user = pass = host = path = decodedpath = puser = ppass = NULL; -#ifdef __GNUC__ /* shut up gcc warnings */ - (void)&closefunc; - (void)&fin; - (void)&fout; - (void)&buf; - (void)&savefile; - (void)&rval; - (void)&isproxy; - (void)&hcode; - (void)&ischunked; - (void)&message; - (void)&location; - (void)&auth; - (void)&decodedpath; -#endif - if (parse_url(url, "URL", &urltype, &user, &pass, &host, &port, &portnum, &path) == -1) goto cleanup_fetch_url; @@ -550,7 +549,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) rval = fetch_ftp(url); goto cleanup_fetch_url; } - warnx("no file after directory (you must specify an " + warnx("No file after directory (you must specify an " "output file) `%s'", url); goto cleanup_fetch_url; } else { @@ -570,7 +569,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) direction = "copied"; fin = fopen(decodedpath, "r"); if (fin == NULL) { - warn("Cannot open file `%s'", decodedpath); + warn("Can't open `%s'", decodedpath); goto cleanup_fetch_url; } if (fstat(fileno(fin), &sb) == 0) { @@ -579,7 +578,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } if (restart_point) { if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) { - warn("Can't lseek to restart `%s'", + warn("Can't seek to restart `%s'", decodedpath); goto cleanup_fetch_url; } @@ -692,7 +691,9 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) hints.ai_protocol = 0; error = getaddrinfo(host, NULL, &hints, &res0); if (error) { - warnx("%s: %s", host, gai_strerror(error)); + warnx("Can't lookup `%s': %s", host, + (error == EAI_SYSTEM) ? strerror(errno) + : gai_strerror(error)); goto cleanup_fetch_url; } if (res0->ai_canonname) @@ -700,13 +701,10 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) s = -1; for (res = res0; res; res = res->ai_next) { - /* - * see comment in hookup() - */ ai_unmapped(res); if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) - strlcpy(hbuf, "invalid", sizeof(hbuf)); + strlcpy(hbuf, "?", sizeof(hbuf)); if (verbose && res0->ai_next) { fprintf(ttyout, "Trying %s...\n", hbuf); @@ -717,12 +715,13 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); if (s < 0) { - warn("Can't create socket"); + warn( + "Can't create socket for connection to `%s'", + hbuf); continue; } if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) { - warn("Connect to address `%s'", hbuf); close(s); s = -1; continue; @@ -733,7 +732,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } if (s < 0) { - warn("Can't connect to %s", host); + warnx("Can't connect to `%s'", host); goto cleanup_fetch_url; } @@ -952,12 +951,12 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } else if (match_token(&cp, "Transfer-Encoding:")) { if (match_token(&cp, "binary")) { warnx( - "Bogus transfer encoding - `binary' (fetching anyway)"); + "Bogus transfer encoding `binary' (fetching anyway)"); continue; } if (! (token = match_token(&cp, "chunked"))) { warnx( - "Unsupported transfer encoding - `%s'", + "Unsupported transfer encoding `%s'", token); goto cleanup_fetch_url; } @@ -1067,7 +1066,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) #endif default: if (message) - warnx("Error retrieving file - `%s'", message); + warnx("Error retrieving file `%s'", message); else warnx("Unknown error retrieving file"); goto cleanup_fetch_url; @@ -1081,7 +1080,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) oldintp = xsignal(SIGPIPE, SIG_IGN); fout = popen(savefile + 1, "w"); if (fout == NULL) { - warn("Can't run `%s'", savefile + 1); + warn("Can't execute `%s'", savefile + 1); goto cleanup_fetch_url; } closefunc = pclose; diff --git a/contrib/tnftp/ftp.1 b/contrib/tnftp/ftp.1 index f1cffbe52f..ea2a50dda4 100644 --- a/contrib/tnftp/ftp.1 +++ b/contrib/tnftp/ftp.1 @@ -1,6 +1,6 @@ -.\" $NetBSD: ftp.1,v 1.114 2006/10/27 01:29:17 lukem Exp $ +.\" $NetBSD: ftp.1,v 1.115 2007/04/17 05:52:03 lukem Exp $ .\" -.\" Copyright (c) 1996-2006 The NetBSD Foundation, Inc. +.\" Copyright (c) 1996-2007 The NetBSD Foundation, Inc. .\" All rights reserved. .\" .\" This code is derived from software contributed to The NetBSD Foundation @@ -64,7 +64,7 @@ .\" .\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 .\" -.Dd October 27, 2006 +.Dd April 16, 2007 .Dt FTP 1 .Os .Sh NAME @@ -86,6 +86,7 @@ Internet file transfer program .Bk -words .Op Fl q Ar quittime .Ek +.Op Fl s Ar srcaddr .Bk -words .Op Fl r Ar retry .Ek @@ -179,7 +180,7 @@ below for more information. .Pp Options may be specified at the command line, or to the command interpreter. -.Bl -tag -width "port " +.Bl -tag -width Fl .It Fl 4 Forces .Nm @@ -272,16 +273,20 @@ if the server does not support passive connections. .It Fl P Ar port Sets the port number to .Ar port . -.It Fl r Ar wait -Retry the connection attempt if it failed, pausing for -.Ar wait -seconds. .It Fl q Ar quittime Quit if the connection has stalled for .Ar quittime seconds. +.It Fl r Ar wait +Retry the connection attempt if it failed, pausing for +.Ar wait +seconds. .It Fl R Restart all non-proxied auto-fetches. +.It Fl s Ar srcaddr +Uses +.Ar srcaddr +as the local IP address for all connections. .It Fl t Enables packet tracing. .It Xo @@ -352,7 +357,7 @@ is provided to the user. The following commands are recognized by .Nm ftp : -.Bl -tag -width Fl +.Bl -tag -width Ic .It Ic \&! Op Ar command Op Ar args Invoke an interactive shell on the local machine. If there are arguments, the first is taken to be a command to execute diff --git a/contrib/tnftp/ftp.c b/contrib/tnftp/ftp.c index 5a77d3b6ba..b6cc64f124 100644 --- a/contrib/tnftp/ftp.c +++ b/contrib/tnftp/ftp.c @@ -1,7 +1,7 @@ -/* $NetBSD: ftp.c,v 1.142 2006/10/23 19:53:24 christos Exp $ */ +/* $NetBSD: ftp.c,v 1.148 2007/04/18 01:50:45 lukem Exp $ */ /*- - * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1996-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -99,7 +99,7 @@ #if 0 static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; #else -__RCSID("$NetBSD: ftp.c,v 1.142 2006/10/23 19:53:24 christos Exp $"); +__RCSID("$NetBSD: ftp.c,v 1.148 2007/04/18 01:50:45 lukem Exp $"); #endif #endif /* not lint */ @@ -168,7 +168,6 @@ hookup(char *host, char *port) struct addrinfo hints, *res, *res0; char hbuf[MAXHOSTNAMELEN]; static char hostnamebuf[MAXHOSTNAMELEN]; - char *cause = "unknown"; socklen_t len; int on = 1; @@ -182,7 +181,9 @@ hookup(char *host, char *port) hints.ai_protocol = 0; error = getaddrinfo(host, NULL, &hints, &res0); if (error) { - warnx("%s: %s", host, gai_strerror(error)); + warnx("Can't lookup `%s': %s", host, + (error == EAI_SYSTEM) ? strerror(errno) + : gai_strerror(error)); code = -1; return (0); } @@ -195,49 +196,22 @@ hookup(char *host, char *port) hostname = hostnamebuf; for (res = res0; res; res = res->ai_next) { - /* - * make sure that ai_addr is NOT an IPv4 mapped address. - * IPv4 mapped address complicates too many things in FTP - * protocol handling, as FTP protocol is defined differently - * between IPv4 and IPv6. - * - * This may not be the best way to handle this situation, - * since the semantics of IPv4 mapped address is defined in - * the kernel. There are configurations where we should use - * IPv4 mapped address as native IPv6 address, not as - * "an IPv6 address that embeds IPv4 address" (namely, SIIT). - * - * More complete solution would be to have an additional - * getsockopt to grab "real" peername/sockname. "real" - * peername/sockname will be AF_INET if IPv4 mapped address - * is used to embed IPv4 address, and will be AF_INET6 if - * we use it as native. What a mess! - */ ai_unmapped(res); + if (getnameinfo(res->ai_addr, res->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) + strlcpy(hbuf, "?", sizeof(hbuf)); if (verbose && res0->ai_next) { /* if we have multiple possibilities */ - if (getnameinfo(res->ai_addr, res->ai_addrlen, - hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) - strlcpy(hbuf, "?", sizeof(hbuf)); fprintf(ttyout, "Trying %s...\n", hbuf); } ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(portnum); s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); if (s < 0) { - cause = "socket"; + warn("Can't create socket for connection to `%s'", + hbuf); continue; } - error = ftp_connect(s, res->ai_addr, res->ai_addrlen); - if (error) { - /* this "if" clause is to prevent print warning twice */ - if (res->ai_next) { - if (getnameinfo(res->ai_addr, res->ai_addrlen, - hbuf, sizeof(hbuf), NULL, 0, - NI_NUMERICHOST)) - strlcpy(hbuf, "?", sizeof(hbuf)); - warn("connect to address %s", hbuf); - } - cause = "connect"; + if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) { close(s); s = -1; continue; @@ -247,7 +221,7 @@ hookup(char *host, char *port) break; } if (s < 0) { - warn("%s", cause); + warnx("Can't connect to `%s'", host); code = -1; freeaddrinfo(res0); return 0; @@ -259,7 +233,7 @@ hookup(char *host, char *port) len = hisctladdr.su_len; if (getsockname(s, (struct sockaddr *)&myctladdr.si_su, &len) == -1) { - warn("getsockname"); + warn("Can't determine my address of connection to `%s'", host); code = -1; goto bad; } @@ -278,7 +252,7 @@ hookup(char *host, char *port) cin = fdopen(s, "r"); cout = fdopen(s, "w"); if (cin == NULL || cout == NULL) { - warnx("fdopen failed."); + warnx("Can't fdopen socket"); if (cin) (void)fclose(cin); if (cout) @@ -360,7 +334,7 @@ command(const char *fmt, ...) } #endif if (cout == NULL) { - warnx("No control connection for command."); + warnx("No control connection for command"); code = -1; return (0); } @@ -455,7 +429,7 @@ getreply(int expecteof) midx = 1; else midx = 2; - (void)fprintf(ttyout, + (void)fprintf(ttyout, "421 Service not available, %s.\n", m421[midx]); (void)fflush(ttyout); } @@ -505,7 +479,7 @@ getreply(int expecteof) if (verbose > 0 || ((verbose > -1 && n == '5') && (n < '5' || !retry_connect))) { (void)putc(c, ttyout); - (void)fflush (ttyout); + (void)fflush(ttyout); } if (cp[-1] == '\r') cp[-1] = '\0'; @@ -585,8 +559,7 @@ abortxfer(int notused) strlcpy(msgbuf, "\nsend", sizeof(msgbuf)); break; default: - errx(1, "abortxfer called with unknown direction `%s'", - direction); + errx(1, "abortxfer: unknown direction `%s'", direction); } len = strlcat(msgbuf, " aborted. Waiting for remote to finish abort.\n", sizeof(msgbuf)); @@ -600,25 +573,18 @@ sendrequest(const char *cmd, const char *local, const char *remote, { struct stat st; int c, d; - FILE *fin, *dout; - int (*closefunc)(FILE *); - sigfunc oldintr, oldintp; - volatile off_t hashbytes; - char *lmode, *bufp; + FILE *volatile fin; + FILE *volatile dout; + int (*volatile closefunc)(FILE *); + sigfunc volatile oldintr; + sigfunc volatile oldintp; + off_t volatile hashbytes; + char *volatile lmode; + char *bufp; static size_t bufsize; static char *buf; int oprogress; -#ifdef __GNUC__ /* to shut up gcc warnings */ - (void)&fin; - (void)&dout; - (void)&closefunc; - (void)&oldintr; - (void)&oldintp; - (void)&lmode; - fin = NULL; /* XXX gcc4 */ -#endif - hashbytes = mark; direction = "sent"; dout = NULL; @@ -656,7 +622,7 @@ sendrequest(const char *cmd, const char *local, const char *remote, oldintp = xsignal(SIGPIPE, SIG_IGN); fin = popen(local + 1, "r"); if (fin == NULL) { - warn("%s", local + 1); + warn("Can't execute `%s'", local + 1); code = -1; goto cleanupsend; } @@ -665,7 +631,7 @@ sendrequest(const char *cmd, const char *local, const char *remote, } else { fin = fopen(local, "r"); if (fin == NULL) { - warn("local: %s", local); + warn("Can't open `%s'", local); code = -1; goto cleanupsend; } @@ -699,7 +665,7 @@ sendrequest(const char *cmd, const char *local, const char *remote, break; } if (rc < 0) { - warn("local: %s", local); + warn("Can't seek to restart `%s'", local); goto cleanupsend; } if (command("REST " LLF, (LLT)restart_point) != CONTINUE) @@ -798,10 +764,10 @@ sendrequest(const char *cmd, const char *local, const char *remote, (void)putc('\n', ttyout); } if (c < 0) - warn("local: %s", local); + warn("Reading `%s'", local); if (d < 0) { if (errno != EPIPE) - warn("netout"); + warn("Writing to network"); bytes = -1; } break; @@ -835,10 +801,10 @@ sendrequest(const char *cmd, const char *local, const char *remote, (void)putc('\n', ttyout); } if (ferror(fin)) - warn("local: %s", local); + warn("Reading `%s'", local); if (ferror(dout)) { if (errno != EPIPE) - warn("netout"); + warn("Writing to network"); bytes = -1; } break; @@ -895,32 +861,27 @@ sendrequest(const char *cmd, const char *local, const char *remote, } void -recvrequest(const char *cmd, const char *local, const char *remote, +recvrequest(const char *cmd, const char *volatile local, const char *remote, const char *lmode, int printnames, int ignorespecial) { - FILE *fout, *din; - int (*closefunc)(FILE *); - sigfunc oldintr, oldintp; + FILE *volatile fout; + FILE *volatile din; + int (*volatile closefunc)(FILE *); + sigfunc volatile oldintr; + sigfunc volatile oldintp; int c, d; - volatile int is_retr, tcrflag, bare_lfs; + int volatile is_retr; + int volatile tcrflag; + int volatile bare_lfs; static size_t bufsize; static char *buf; - volatile off_t hashbytes; + off_t volatile hashbytes; struct stat st; time_t mtime; struct timeval tval[2]; int oprogress; int opreserve; -#ifdef __GNUC__ /* to shut up gcc warnings */ - (void)&local; - (void)&fout; - (void)&din; - (void)&closefunc; - (void)&oldintr; - (void)&oldintp; -#endif - fout = NULL; din = NULL; hashbytes = mark; @@ -958,7 +919,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, char *dir = strrchr(local, '/'); if (errno != ENOENT && errno != EACCES) { - warn("local: %s", local); + warn("Can't access `%s'", local); code = -1; goto cleanuprecv; } @@ -969,13 +930,13 @@ recvrequest(const char *cmd, const char *local, const char *remote, if (dir != NULL) *dir = '/'; if (d < 0) { - warn("local: %s", local); + warn("Can't access `%s'", local); code = -1; goto cleanuprecv; } if (!runique && errno == EACCES && chmod(local, (S_IRUSR|S_IWUSR)) < 0) { - warn("local: %s", local); + warn("Can't chmod `%s'", local); code = -1; goto cleanuprecv; } @@ -1027,7 +988,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, oldintp = xsignal(SIGPIPE, SIG_IGN); fout = popen(local + 1, "w"); if (fout == NULL) { - warn("%s", local+1); + warn("Can't execute `%s'", local+1); goto abort; } progress = 0; @@ -1036,7 +997,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, } else { fout = fopen(local, lmode); if (fout == NULL) { - warn("local: %s", local); + warn("Can't open `%s'", local); goto abort; } closefunc = fclose; @@ -1061,7 +1022,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, case TYPE_L: if (is_retr && restart_point && lseek(fileno(fout), restart_point, SEEK_SET) < 0) { - warn("local: %s", local); + warn("Can't seek to restart `%s'", local); goto cleanuprecv; } if (rate_get) { /* rate limiting */ @@ -1123,14 +1084,14 @@ recvrequest(const char *cmd, const char *local, const char *remote, } if (c < 0) { if (errno != EPIPE) - warn("netin"); + warn("Reading from network"); bytes = -1; } if (d < c) { if (d < 0) - warn("local: %s", local); + warn("Writing `%s'", local); else - warnx("%s: short write", local); + warnx("Writing `%s': short write", local); } break; @@ -1149,7 +1110,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, } if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { done: - warn("local: %s", local); + warn("Can't seek to restart `%s'", local); goto cleanuprecv; } } @@ -1188,11 +1149,11 @@ recvrequest(const char *cmd, const char *local, const char *remote, } if (ferror(din)) { if (errno != EPIPE) - warn("netin"); + warn("Reading from network"); bytes = -1; } if (ferror(fout)) - warn("local: %s", local); + warn("Writing `%s'", local); break; } @@ -1279,22 +1240,24 @@ initconn(void) unsigned int af, hal, pal; socklen_t len; char *pasvcmd = NULL; + int overbose; #ifdef INET6 #ifndef NO_DEBUG if (myctladdr.su_family == AF_INET6 && ftp_debug && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.si_su.su_sin6.sin6_addr) || IN6_IS_ADDR_SITELOCAL(&myctladdr.si_su.su_sin6.sin6_addr))) { - warnx("use of scoped address can be troublesome"); + warnx("Use of scoped addresses can be troublesome"); } #endif #endif + reinit: if (passivemode) { data_addr = myctladdr; data = socket(data_addr.su_family, SOCK_STREAM, 0); if (data < 0) { - warn("socket"); + warn("Can't create socket for data connection"); return (1); } if ((options & SO_DEBUG) && @@ -1307,7 +1270,14 @@ initconn(void) case AF_INET: if (epsv4 && !epsv4bad) { pasvcmd = "EPSV"; + overbose = verbose; + if (ftp_debug == 0) + verbose = -1; result = command("EPSV"); + verbose = overbose; + if (verbose > 0 && + (result == COMPLETE || !connected)) + fprintf(ttyout, "%s\n", reply_string); if (!connected) return (1); /* @@ -1336,7 +1306,14 @@ initconn(void) #ifdef INET6 case AF_INET6: pasvcmd = "EPSV"; + overbose = verbose; + if (ftp_debug == 0) + verbose = -1; result = command("EPSV"); + verbose = overbose; + if (verbose > 0 && + (result == COMPLETE || !connected)) + fprintf(ttyout, "%s\n", reply_string); if (!connected) return (1); /* this code is to be friendly with broken BSDI ftpd */ @@ -1516,8 +1493,8 @@ initconn(void) } else goto bad; - while (ftp_connect(data, (struct sockaddr *)&data_addr.si_su, - data_addr.su_len) < 0) { + if (ftp_connect(data, (struct sockaddr *)&data_addr.si_su, + data_addr.su_len) < 0) { if (activefallback) { (void)close(data); data = -1; @@ -1527,7 +1504,6 @@ initconn(void) #endif goto reinit; } - warn("connect for data channel"); goto bad; } #ifdef IPTOS_THROUGHPUT @@ -1551,7 +1527,7 @@ initconn(void) (void)close(data); data = socket(data_addr.su_family, SOCK_STREAM, 0); if (data < 0) { - warn("socket"); + warn("Can't create socket for data connection"); if (tmpno) sendport = 1; return (1); @@ -1559,12 +1535,12 @@ initconn(void) if (!sendport) if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)) == -1) { - warn("setsockopt %s", "SO_REUSEADDR"); + warn("Can't set SO_REUSEADDR on data connection"); goto bad; } if (bind(data, (struct sockaddr *)&data_addr.si_su, data_addr.su_len) < 0) { - warn("bind"); + warn("Can't bind for data connection"); goto bad; } if ((options & SO_DEBUG) && @@ -1575,12 +1551,12 @@ initconn(void) len = sizeof(data_addr.si_su); memset((char *)&data_addr, 0, sizeof (data_addr)); if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) == -1) { - warn("getsockname"); + warn("Can't determine my address of data connection"); goto bad; } data_addr.su_len = len; if (ftp_listen(data, 1) < 0) - warn("listen"); + warn("Can't listen to data connection"); if (sendport) { char hname[NI_MAXHOST], sname[NI_MAXSERV]; @@ -1608,8 +1584,15 @@ initconn(void) sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) { result = ERROR; } else { + overbose = verbose; + if (ftp_debug == 0) + verbose = -1; result = command("EPRT |%d|%s|%s|", af, hname, sname); + verbose = overbose; + if (verbose > 0 && + (result == COMPLETE || !connected)) + fprintf(ttyout, "%s\n", reply_string); if (!connected) return (1); if (result != COMPLETE) { @@ -1717,11 +1700,11 @@ dataconn(const char *lmode) rv = ftp_poll(pfd, 1, timeout); } while (rv == -1 && errno == EINTR); /* loop until poll ! EINTR */ if (rv == -1) { - warn("poll waiting before accept"); + warn("Can't poll waiting before accept"); goto dataconn_failed; } if (rv == 0) { - warn("poll timeout waiting before accept"); + warnx("Poll timeout waiting before accept"); goto dataconn_failed; } @@ -1731,7 +1714,7 @@ dataconn(const char *lmode) s = accept(data, (struct sockaddr *) &from.si_su, &fromlen); } while (s == -1 && errno == EINTR); /* loop until accept ! EINTR */ if (s == -1) { - warn("accept"); + warn("Can't accept data connection"); goto dataconn_failed; } @@ -1872,15 +1855,10 @@ abortpt(int notused) void proxtrans(const char *cmd, const char *local, const char *remote) { - sigfunc oldintr; + sigfunc volatile oldintr; int prox_type, nfnd; - volatile int secndflag; - char *cmd2; - -#ifdef __GNUC__ /* to shut up gcc warnings */ - (void)&oldintr; - (void)&cmd2; -#endif + int volatile secndflag; + char *volatile cmd2; oldintr = NULL; secndflag = 0; @@ -1984,7 +1962,7 @@ proxtrans(const char *cmd, const char *local, const char *remote) if (cpend) { if ((nfnd = empty(cin, NULL, 10)) <= 0) { if (nfnd < 0) - warn("abort"); + warn("Error aborting proxy command"); if (ptabflg) code = -1; lostpeer(0); @@ -2012,7 +1990,7 @@ reset(int argc, char *argv[]) } while (nfnd > 0) { if ((nfnd = empty(cin, NULL, 0)) < 0) { - warn("reset"); + warn("Error resetting connection"); code = -1; lostpeer(0); } else if (nfnd) @@ -2034,7 +2012,7 @@ gunique(const char *local) if (cp) *cp = '/'; if (d < 0) { - warn("local: %s", local); + warn("Can't access `%s'", local); return (NULL); } len = strlcpy(new, local, sizeof(new)); @@ -2094,7 +2072,7 @@ abort_remote(FILE *din) int nfnd; if (cout == NULL) { - warnx("Lost control connection for abort."); + warnx("Lost control connection for abort"); if (ptabflg) code = -1; lostpeer(0); @@ -2108,12 +2086,12 @@ abort_remote(FILE *din) buf[1] = IP; buf[2] = IAC; if (send(fileno(cout), buf, 3, MSG_OOB) != 3) - warn("abort"); + warn("Can't send abort message"); fprintf(cout, "%cABOR\r\n", DM); (void)fflush(cout); if ((nfnd = empty(cin, din, 10)) <= 0) { if (nfnd < 0) - warn("abort"); + warn("Can't send abort message"); if (ptabflg) code = -1; lostpeer(0); @@ -2129,6 +2107,24 @@ abort_remote(FILE *din) (void)getreply(0); } +/* + * Ensure that ai->ai_addr is NOT an IPv4 mapped address. + * IPv4 mapped address complicates too many things in FTP + * protocol handling, as FTP protocol is defined differently + * between IPv4 and IPv6. + * + * This may not be the best way to handle this situation, + * since the semantics of IPv4 mapped address is defined in + * the kernel. There are configurations where we should use + * IPv4 mapped address as native IPv6 address, not as + * "an IPv6 address that embeds IPv4 address" (namely, SIIT). + * + * More complete solution would be to have an additional + * getsockopt to grab "real" peername/sockname. "real" + * peername/sockname will be AF_INET if IPv4 mapped address + * is used to embed IPv4 address, and will be AF_INET6 if + * we use it as native. What a mess! + */ void ai_unmapped(struct addrinfo *ai) { diff --git a/contrib/tnftp/ftp_var.h b/contrib/tnftp/ftp_var.h index 3c8a31bea0..0997376df4 100644 --- a/contrib/tnftp/ftp_var.h +++ b/contrib/tnftp/ftp_var.h @@ -1,7 +1,7 @@ -/* $NetBSD: ftp_var.h,v 1.73 2006/01/31 20:05:36 christos Exp $ */ +/* $NetBSD: ftp_var.h,v 1.74 2007/04/17 05:52:03 lukem Exp $ */ /*- - * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1996-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -210,7 +210,7 @@ GLOBAL int sendport; /* use PORT/LPRT cmd for each data connection */ GLOBAL int connected; /* 1 = connected to server, -1 = logged in */ GLOBAL int interactive; /* interactively prompt on m* cmds */ GLOBAL int confirmrest; /* confirm rest of current m* cmd */ -GLOBAL int ftp_debug; /* debugging level */ +GLOBAL int ftp_debug; /* debugging level */ GLOBAL int bell; /* ring bell on cmd completion */ GLOBAL int doglob; /* glob local file names */ GLOBAL int autologin; /* establish user account on connection */ @@ -279,6 +279,7 @@ GLOBAL sa_family_t family; /* address family to use for connections */ GLOBAL char *ftpport; /* port number to use for FTP connections */ GLOBAL char *httpport; /* port number to use for HTTP connections */ GLOBAL char *gateport; /* port number to use for gateftp connections */ +GLOBAL struct addrinfo *bindai; /* local address to bind as */ GLOBAL char *outfile; /* filename to output URLs to */ GLOBAL int restartautofetch; /* restart auto-fetch */ diff --git a/contrib/tnftp/main.c b/contrib/tnftp/main.c index 443654cf76..c7740debe8 100644 --- a/contrib/tnftp/main.c +++ b/contrib/tnftp/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.101 2006/01/31 20:05:36 christos Exp $ */ +/* $NetBSD: main.c,v 1.104 2007/04/17 05:52:03 lukem Exp $ */ /*- * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. @@ -104,7 +104,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\ #if 0 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94"; #else -__RCSID("$NetBSD: main.c,v 1.101 2006/01/31 20:05:36 christos Exp $"); +__RCSID("$NetBSD: main.c,v 1.104 2007/04/17 05:52:03 lukem Exp $"); #endif #endif /* not lint */ @@ -138,11 +138,11 @@ static void setupoption(char *, char *, char *); int main(int, char *[]); int -main(int argc, char *argv[]) +main(int volatile argc, char **volatile argv) { int ch, rval; struct passwd *pw; - char *cp, *ep, *anonuser, *anonpass, *upload_path; + char *cp, *ep, *anonuser, *anonpass, *upload_path, *src_addr; int dumbterm, s, isupload; size_t len; socklen_t slen; @@ -189,6 +189,7 @@ main(int argc, char *argv[]) epsv4 = 0; #endif epsv4bad = 0; + src_addr = NULL; upload_path = NULL; isupload = 0; reply_callback = NULL; @@ -207,15 +208,15 @@ main(int argc, char *argv[]) */ s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1) - err(1, "can't create socket"); + err(1, "Can't create socket to determine default socket sizes"); slen = sizeof(rcvbuf_size); if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf_size, &slen) == -1) - err(1, "unable to get default rcvbuf size"); + err(1, "Unable to get default rcvbuf size"); slen = sizeof(sndbuf_size); if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf_size, &slen) == -1) - err(1, "unable to get default sndbuf size"); + err(1, "Unable to get default sndbuf size"); (void)close(s); /* sanity check returned buffer sizes */ if (rcvbuf_size <= 0) @@ -246,7 +247,7 @@ main(int argc, char *argv[]) passivemode = 1; activefallback = 1; } else - warnx("unknown $FTPMODE '%s'; using defaults", cp); + warnx("Unknown $FTPMODE `%s'; using defaults", cp); } if (strcmp(getprogname(), "pftp") == 0) { @@ -287,7 +288,7 @@ main(int argc, char *argv[]) } } - while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:RtT:u:vV")) != -1) { + while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:Rs:tT:u:vV")) != -1) { switch (ch) { case '4': family = AF_INET; @@ -362,19 +363,23 @@ main(int argc, char *argv[]) case 'q': quit_time = strtol(optarg, &ep, 10); if (quit_time < 1 || *ep != '\0') - errx(1, "bad quit value: %s", optarg); + errx(1, "Bad quit value: %s", optarg); break; case 'r': retry_connect = strtol(optarg, &ep, 10); if (retry_connect < 1 || *ep != '\0') - errx(1, "bad retry value: %s", optarg); + errx(1, "Bad retry value: %s", optarg); break; case 'R': restartautofetch = 1; break; + case 's': + src_addr = optarg; + break; + case 't': trace = 1; break; @@ -391,7 +396,8 @@ main(int argc, char *argv[]) while ((cp = strsep(&oac, ",")) != NULL) { if (*cp == '\0') { - warnx("bad throttle value: %s", optarg); + warnx("Bad throttle value `%s'", + optarg); usage(); /* NOTREACHED */ } @@ -436,6 +442,22 @@ main(int argc, char *argv[]) crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ + if (src_addr != NULL) { + struct addrinfo hints; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + error = getaddrinfo(src_addr, NULL, &hints, &bindai); + if (error) { + errx(1, "Can't lookup `%s': %s", src_addr, + (error == EAI_SYSTEM) ? strerror(errno) + : gai_strerror(error)); + } + } + /* * Cache the user name and home directory. */ @@ -503,11 +525,6 @@ main(int argc, char *argv[]) (void)xsignal(SIGUSR2, crankrate); (void)xsignal(SIGWINCH, setttywidth); -#ifdef __GNUC__ /* to shut up gcc warnings */ - (void)&argc; - (void)&argv; -#endif - if (argc > 0) { if (isupload) { rval = auto_put(argc, argv, upload_path); @@ -595,7 +612,7 @@ prompt(void) o = getoption("prompt"); if (o == NULL) - errx(1, "no such option `prompt'"); + errx(1, "prompt: no such option `prompt'"); prompt = &(o->value); } formatbuf(buf, sizeof(buf), *prompt ? *prompt : DEFAULTPROMPT); @@ -616,7 +633,7 @@ rprompt(void) o = getoption("rprompt"); if (o == NULL) - errx(1, "no such option `rprompt'"); + errx(1, "rprompt: no such option `rprompt'"); rprompt = &(o->value); } formatbuf(buf, sizeof(buf), *rprompt ? *rprompt : DEFAULTRPROMPT); @@ -645,8 +662,8 @@ cmdscanner(void) p = rprompt(); if (*p) fprintf(ttyout, "%s ", p); - (void)fflush(ttyout); } + (void)fflush(ttyout); num = getline(stdin, line, sizeof(line), NULL); switch (num) { case -1: /* EOF */ @@ -1016,11 +1033,11 @@ getoptionvalue(const char *name) struct option *c; if (name == NULL) - errx(1, "getoptionvalue() invoked with NULL name"); + errx(1, "getoptionvalue: invoked with NULL name"); c = getoption(name); if (c != NULL) return (c->value); - errx(1, "getoptionvalue() invoked with unknown option `%s'", name); + errx(1, "getoptionvalue: invoked with unknown option `%s'", name); /* NOTREACHED */ } @@ -1046,8 +1063,9 @@ usage(void) (void)fprintf(stderr, "usage: %s [-46AadefginpRtvV] [-N netrc] [-o outfile] [-P port] [-q quittime]\n" -" [-r retry] [-T dir,max[,inc][[user@]host [port]]] [host:path[/]]\n" -" [file:///file] [ftp://[user[:pass]@]host[:port]/path[/]]\n" +" [-r retry] [-s srcaddr] [-T dir,max[,inc]]\n" +" [[user@]host [port]] [host:path[/]] [file:///file]\n" +" [ftp://[user[:pass]@]host[:port]/path[/]]\n" " [http://[user[:pass]@]host[:port]/path] [...]\n" " %s -u URL file [...]\n", progname, progname); exit(1); diff --git a/contrib/tnftp/progressbar.c b/contrib/tnftp/progressbar.c index 0e779d0d84..34d3cc6b28 100644 --- a/contrib/tnftp/progressbar.c +++ b/contrib/tnftp/progressbar.c @@ -1,7 +1,7 @@ -/* $NetBSD: progressbar.c,v 1.13 2006/05/01 23:02:03 christos Exp $ */ +/* $NetBSD: progressbar.c,v 1.15 2007/04/17 05:52:03 lukem Exp $ */ /*- - * Copyright (c) 1997-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1997-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -38,7 +38,7 @@ #include #ifndef lint -__RCSID("$NetBSD: progressbar.c,v 1.13 2006/05/01 23:02:03 christos Exp $"); +__RCSID("$NetBSD: progressbar.c,v 1.15 2007/04/17 05:52:03 lukem Exp $"); #endif /* not lint */ /* @@ -91,10 +91,23 @@ updateprogressmeter(int dummy) } /* - * List of order of magnitude prefixes. - * The last is `P', as 2^64 = 16384 Petabytes + * List of order of magnitude suffixes, per IEC 60027-2. */ -static const char prefixes[] = " KMGTP"; +static const char const *suffixes[] = { + "", /* 2^0 (byte) */ + "KiB", /* 2^10 Kibibyte */ + "MiB", /* 2^20 Mebibyte */ + "GiB", /* 2^30 Gibibyte */ + "TiB", /* 2^40 Tebibyte */ + "PiB", /* 2^50 Pebibyte */ + "EiB", /* 2^60 Exbibyte */ +#if 0 + /* The following are not necessary for signed 64-bit off_t */ + "ZiB", /* 2^70 Zebibyte */ + "YiB", /* 2^80 Yobibyte */ +#endif +}; +#define NSUFFIXES (sizeof(suffixes) / sizeof(suffixes[0])) /* * Display a transfer progress bar if progress is non-zero. @@ -135,7 +148,7 @@ progressmeter(int flag) size_t len; char buf[256]; /* workspace for progress bar */ #ifndef NO_PROGRESS -#define BAROVERHEAD 43 /* non `*' portion of progress bar */ +#define BAROVERHEAD 45 /* non `*' portion of progress bar */ /* * stars should contain at least * sizeof(buf) - BAROVERHEAD entries @@ -224,14 +237,13 @@ progressmeter(int flag) } abbrevsize = cursize; - for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++) + for (i = 0; abbrevsize >= 100000 && i < NSUFFIXES; i++) abbrevsize >>= 10; - if (i == sizeof(prefixes)) + if (i == NSUFFIXES) i--; - len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ", + len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %-3s ", (LLT)abbrevsize, - prefixes[i], - i == 0 ? ' ' : 'B'); + suffixes[i]); timersub(&now, &start, &td); elapsed = td.tv_sec + (td.tv_usec / 1000000.0); @@ -242,13 +254,13 @@ progressmeter(int flag) if (elapsed > 0.0) bytespersec /= elapsed; } - for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) + for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++) bytespersec >>= 10; len += snprintf(buf + len, BUFLEFT, - " " LLFP("3") ".%02d %cB/s ", + " " LLFP("3") ".%02d %.2sB/s ", (LLT)(bytespersec / 1024), (int)((bytespersec % 1024) * 100 / 1024), - prefixes[i]); + suffixes[i]); if (filesize > 0) { if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) { @@ -334,14 +346,14 @@ ptransfer(int siginfo) len += snprintf(buf + len, BUFLEFT, "%02d:%02d ", remaining / 60, remaining % 60); - for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) + for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++) bytespersec >>= 10; - if (i == sizeof(prefixes)) + if (i == NSUFFIXES) i--; - len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)", + len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %.2sB/s)", (LLT)(bytespersec / 1024), (int)((bytespersec % 1024) * 100 / 1024), - prefixes[i]); + suffixes[i]); if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0 && bytes + restart_point <= filesize) { @@ -459,7 +471,7 @@ xsignal(int sig, sigfunc func) * This is unpleasant, but I don't know what would be better. * Right now, this "can't happen" */ - errx(1, "xsignal_restart called with signal %d", sig); + errx(1, "xsignal_restart: called with signal %d", sig); } return(xsignal_restart(sig, func, restartable)); diff --git a/contrib/tnftp/ruserpass.c b/contrib/tnftp/ruserpass.c index 5b4683fb74..e434052784 100644 --- a/contrib/tnftp/ruserpass.c +++ b/contrib/tnftp/ruserpass.c @@ -1,4 +1,4 @@ -/* $NetBSD: ruserpass.c,v 1.31 2006/01/31 20:01:23 christos Exp $ */ +/* $NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp $ */ /* * Copyright (c) 1985, 1993, 1994 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; #else -__RCSID("$NetBSD: ruserpass.c,v 1.31 2006/01/31 20:01:23 christos Exp $"); +__RCSID("$NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp $"); #endif #endif /* not lint */ @@ -93,7 +93,7 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) cfile = fopen(netrc, "r"); if (cfile == NULL) { if (errno != ENOENT) - warn("%s", netrc); + warn("Can't read `%s'", netrc); return (0); } if (gethostname(myname, sizeof(myname)) < 0) @@ -102,7 +102,7 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) if ((mydomain = strchr(myname, '.')) == NULL) mydomain = ""; next: - while ((t = token())) switch(t) { + while ((t = token()) > 0) switch(t) { case DEFAULT: usedefault = 1; @@ -110,7 +110,9 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) case MACH: if (!usedefault) { - if (token() != ID) + if ((t = token()) == -1) + goto bad; + if (t != ID) continue; /* * Allow match either for user's input host name @@ -134,10 +136,13 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) continue; } match: - while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + while ((t = token()) > 0 && + t != MACH && t != DEFAULT) switch(t) { case LOGIN: - if (token()) { + if ((t = token()) == -1) + goto bad; + if (t) { if (*aname == NULL) *aname = ftp_strdup(tokval); else { @@ -150,21 +155,25 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) if ((*aname == NULL || strcmp(*aname, "anonymous")) && fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others."); - warnx("Remove password or make file unreadable by others."); + warnx("Error: .netrc file is readable by others"); + warnx("Remove password or make file unreadable by others"); goto bad; } - if (token() && *apass == NULL) + if ((t = token()) == -1) + goto bad; + if (t && *apass == NULL) *apass = ftp_strdup(tokval); break; case ACCOUNT: if (fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others."); - warnx("Remove account or make file unreadable by others."); + warnx("Error: .netrc file is readable by others"); + warnx("Remove account or make file unreadable by others"); goto bad; } - if (token() && *aacct == NULL) + if ((t = token()) == -1) + goto bad; + if (t && *aacct == NULL) *aacct = ftp_strdup(tokval); break; case MACDEF: @@ -225,9 +234,13 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) } *tmp = c; if (*tmp == '\n') { - if (*(tmp-1) == '\0') { - macros[macnum++].mac_end = tmp - 1; - break; + if (tmp == macros[macnum].mac_start) { + macros[macnum++].mac_end = tmp; + break; + } else if (*(tmp - 1) == '\0') { + macros[macnum++].mac_end = + tmp - 1; + break; } *tmp = '\0'; } @@ -240,12 +253,14 @@ ruserpass(const char *host, char **aname, char **apass, char **aacct) } break; default: - warnx("Unknown .netrc keyword %s", tokval); + warnx("Unknown .netrc keyword `%s'", tokval); break; } goto done; } done: + if (t == -1) + goto bad; (void)fclose(cfile); return (0); bad: @@ -271,16 +286,26 @@ token(void) if (c == '"') { while ((c = getc(cfile)) != EOF && c != '"') { if (c == '\\') - c = getc(cfile); + if ((c = getc(cfile)) == EOF) + break; *cp++ = c; + if (cp == tokval + sizeof(tokval)) { + warnx("Token in .netrc too long"); + return (-1); + } } } else { *cp++ = c; while ((c = getc(cfile)) != EOF && c != '\n' && c != '\t' && c != ' ' && c != ',') { if (c == '\\') - c = getc(cfile); + if ((c = getc(cfile)) == EOF) + break; *cp++ = c; + if (cp == tokval + sizeof(tokval)) { + warnx("Token in .netrc too long"); + return (-1); + } } } *cp = 0; diff --git a/contrib/tnftp/util.c b/contrib/tnftp/util.c index 0e17f1f41a..6162fbc5f3 100644 --- a/contrib/tnftp/util.c +++ b/contrib/tnftp/util.c @@ -1,7 +1,7 @@ -/* $NetBSD: util.c,v 1.135 2006/05/23 23:59:48 jnemeth Exp $ */ +/* $NetBSD: util.c,v 1.138 2007/04/17 05:52:04 lukem Exp $ */ /*- - * Copyright (c) 1997-2005 The NetBSD Foundation, Inc. + * Copyright (c) 1997-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -71,7 +71,7 @@ #include #ifndef lint -__RCSID("$NetBSD: util.c,v 1.135 2006/05/23 23:59:48 jnemeth Exp $"); +__RCSID("$NetBSD: util.c,v 1.138 2007/04/17 05:52:04 lukem Exp $"); #endif /* not lint */ /* @@ -137,7 +137,7 @@ setpeer(int argc, char *argv[]) if (gatemode) { if (gateserver == NULL || *gateserver == '\0') - errx(1, "gateserver not defined (shouldn't happen)"); + errx(1, "main: gateserver not defined"); host = hookup(gateserver, port); } else host = hookup(argv[1], port); @@ -379,6 +379,7 @@ ftp_login(const char *host, const char *luser, const char *lpass) { char tmp[80]; char *user, *pass, *acct, *p; + char emptypass[] = ""; const char *errormsg; int n, aflag, rval, nlen; @@ -443,6 +444,8 @@ ftp_login(const char *host, const char *luser, const char *lpass) if (n == CONTINUE) { if (pass == NULL) { p = getpass("Password: "); + if (p == NULL) + p = emptypass; pass = ftp_strdup(p); memset(p, 0, strlen(p)); } @@ -453,11 +456,13 @@ ftp_login(const char *host, const char *luser, const char *lpass) aflag++; if (acct == NULL) { p = getpass("Account: "); + if (p == NULL) + p = emptypass; acct = ftp_strdup(p); memset(p, 0, strlen(p)); } if (acct[0] == '\0') { - warnx("Login failed."); + warnx("Login failed"); goto cleanup_ftp_login; } n = command("ACCT %s", acct); @@ -465,7 +470,7 @@ ftp_login(const char *host, const char *luser, const char *lpass) } if ((n != COMPLETE) || (!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) { - warnx("Login failed."); + warnx("Login failed"); goto cleanup_ftp_login; } rval = 1; @@ -572,7 +577,7 @@ remglob(char *argv[], int doswitch, const char **errbuf) (void)strlcat(temp, "/", sizeof(temp)); (void)strlcat(temp, TMPFILE, sizeof(temp)); if ((fd = mkstemp(temp)) < 0) { - warn("unable to create temporary file %s", temp); + warn("Unable to create temporary file `%s'", temp); return (NULL); } close(fd); @@ -599,12 +604,10 @@ remglob(char *argv[], int doswitch, const char **errbuf) (void)unlink(temp); if (ftemp == NULL) { if (errbuf == NULL) - fputs( - "can't find list of remote files, oops.\n", - ttyout); + warnx("Can't find list of remote files"); else *errbuf = - "can't find list of remote files, oops."; + "Can't find list of remote files"; return (NULL); } } @@ -638,7 +641,7 @@ globulize(const char *pattern) flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; memset(&gl, 0, sizeof(gl)); if (glob(pattern, flags, NULL, &gl) || gl.gl_pathc == 0) { - warnx("%s: not found", pattern); + warnx("Glob pattern `%s' not found", pattern); globfree(&gl); return (NULL); } @@ -767,7 +770,7 @@ remotemodtime(const char *file, int noisy) goto bad_parse_time; else goto cleanup_parse_time; - } else + } else DPRINTF("parsed date as: %s", ctime(&rtime)); } else { if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1) @@ -845,7 +848,7 @@ fileindir(const char *file, const char *dir) char realdir[PATH_MAX+1]; size_t dirlen; - /* determine parent directory of file */ + /* determine parent directory of file */ (void)strlcpy(parentdirbuf, file, sizeof(parentdirbuf)); parentdir = dirname(parentdirbuf); if (strcmp(parentdir, ".") == 0) @@ -1052,11 +1055,11 @@ setupsockbufsize(int sock) if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&sndbuf_size, sizeof(sndbuf_size)) == -1) - warn("unable to set sndbuf size %d", sndbuf_size); + warn("Unable to set sndbuf size %d", sndbuf_size); if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&rcvbuf_size, sizeof(rcvbuf_size)) == -1) - warn("unable to set rcvbuf size %d", rcvbuf_size); + warn("Unable to set rcvbuf size %d", rcvbuf_size); } /* @@ -1310,14 +1313,15 @@ getline(FILE *stream, char *buf, size_t buflen, const char **errormsg) return len; } - /* - * Internal version of connect(2); sets socket buffer sizes first and + * Internal version of connect(2); sets socket buffer sizes, + * binds to a specific local address (if set), and * supports a connection timeout using a non-blocking connect(2) with * a poll(2). * Socket fcntl flags are temporarily updated to include O_NONBLOCK; * these will not be reverted on connection failure. - * Returns -1 upon failure (with errno set to the problem), or 0 on success. + * Returns 0 on success, or -1 upon failure (with an appropriate + * error message displayed.) */ int ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen) @@ -1326,13 +1330,48 @@ ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen) socklen_t slen; struct timeval endtime, now, td; struct pollfd pfd[1]; + char hname[NI_MAXHOST]; setupsockbufsize(sock); + if (getnameinfo(name, namelen, + hname, sizeof(hname), NULL, 0, NI_NUMERICHOST) != 0) + strlcpy(hname, "?", sizeof(hname)); + + if (bindai != NULL) { /* bind to specific addr */ + struct addrinfo *ai; + + for (ai = bindai; ai != NULL; ai = ai->ai_next) { + if (ai->ai_family == name->sa_family) + break; + } + if (ai == NULL) + ai = bindai; + if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { + char bname[NI_MAXHOST]; + int saveerr; + + saveerr = errno; + if (getnameinfo(ai->ai_addr, ai->ai_addrlen, + bname, sizeof(bname), NULL, 0, NI_NUMERICHOST) != 0) + strlcpy(bname, "?", sizeof(bname)); + errno = saveerr; + warn("Can't bind to `%s'", bname); + return -1; + } + } - if ((flags = fcntl(sock, F_GETFL, 0)) == -1) - return -1; /* get current socket flags */ - if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) - return -1; /* set non-blocking connect */ + /* save current socket flags */ + if ((flags = fcntl(sock, F_GETFL, 0)) == -1) { + warn("Can't %s socket flags for connect to `%s'", + "save", hname); + return -1; + } + /* set non-blocking connect */ + if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) { + warn("Can't set socket non-blocking for connect to `%s'", + hname); + return -1; + } /* NOTE: we now must restore socket flags on successful exit */ @@ -1346,8 +1385,11 @@ ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen) rv = connect(sock, name, namelen); /* inititate the connection */ if (rv == -1) { /* connection error */ - if (errno != EINPROGRESS) /* error isn't "please wait" */ + if (errno != EINPROGRESS) { /* error isn't "please wait" */ + connecterror: + warn("Can't connect to `%s'", hname); return -1; + } /* connect EINPROGRESS; wait */ do { @@ -1367,28 +1409,33 @@ ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen) if (rv == 0) { /* poll (connect) timed out */ errno = ETIMEDOUT; - return -1; + goto connecterror; } if (rv == -1) { /* poll error */ - return -1; + goto connecterror; } else if (pfd[0].revents & (POLLIN|POLLOUT)) { slen = sizeof(error); /* OK, or pending error */ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, - &error, &slen) == -1) - return -1; /* Solaris pending error */ - if (error != 0) { + &error, &slen) == -1) { + /* Solaris pending error */ + goto connecterror; + } else if (error != 0) { errno = error; /* BSD pending error */ - return -1; + goto connecterror; } } else { errno = EBADF; /* this shouldn't happen ... */ - return -1; + goto connecterror; } } - if (fcntl(sock, F_SETFL, flags) == -1) /* restore socket flags */ + if (fcntl(sock, F_SETFL, flags) == -1) { + /* restore socket flags */ + warn("Can't %s socket flags for connect to `%s'", + "restore", hname); return -1; + } return 0; } @@ -1461,7 +1508,7 @@ ftp_strdup(const char *str) char *s; if (str == NULL) - errx(1, "ftp_strdup() called with NULL argument"); + errx(1, "ftp_strdup: called with NULL argument"); s = strdup(str); if (s == NULL) err(1, "Unable to allocate memory for string copy"); diff --git a/contrib/tnftp/version.h b/contrib/tnftp/version.h index d952407ac5..b9937b32b9 100644 --- a/contrib/tnftp/version.h +++ b/contrib/tnftp/version.h @@ -1,6 +1,6 @@ -/* $NetBSD: version.h,v 1.58 2006/07/26 14:28:11 lukem Exp $ */ +/* $NetBSD: version.h,v 1.63 2007/04/18 01:39:04 lukem Exp $ */ /*- - * Copyright (c) 1999-2006 The NetBSD Foundation, Inc. + * Copyright (c) 1999-2007 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -40,5 +40,5 @@ #endif #ifndef FTP_VERSION -#define FTP_VERSION "20060726" +#define FTP_VERSION "20070418" #endif -- 2.41.0