diff options
author | lukem <lukem@pkgsrc.org> | 2007-08-06 04:33:23 +0000 |
---|---|---|
committer | lukem <lukem@pkgsrc.org> | 2007-08-06 04:33:23 +0000 |
commit | 860d827917e42a54d7e7d3bddd60ffbb2743fd2a (patch) | |
tree | 14e64cdb818e9749874609154e29b37a0132c869 | |
parent | 2010d3d3ecad660f61ea015ed0f001fc179cd8b5 (diff) | |
download | pkgsrc-860d827917e42a54d7e7d3bddd60ffbb2743fd2a.tar.gz |
Update to tnftp 20070806.
Notable changes:
- Implement '-s srcaddr' to set the local IP address for all connections.
- Support '-q quittime' when waiting for server replies.
- Use IEC 60027-2 "KiB", "MiB" (etc) instead of "KB", "MB", ...
- Portability fixes, including for FreeBSD, Mac OS X, and Solaris.
-rw-r--r-- | net/tnftp/files/configure.ac | 372 | ||||
-rw-r--r-- | net/tnftp/files/src/cmds.c | 294 | ||||
-rw-r--r-- | net/tnftp/files/src/cmdtab.c | 19 | ||||
-rw-r--r-- | net/tnftp/files/src/complete.c | 51 | ||||
-rw-r--r-- | net/tnftp/files/src/domacro.c | 23 | ||||
-rw-r--r-- | net/tnftp/files/src/fetch.c | 385 | ||||
-rw-r--r-- | net/tnftp/files/src/ftp.1 | 219 | ||||
-rw-r--r-- | net/tnftp/files/src/ftp.c | 614 | ||||
-rw-r--r-- | net/tnftp/files/src/ftp.cat1 | 248 | ||||
-rw-r--r-- | net/tnftp/files/src/ftp_var.h | 40 | ||||
-rw-r--r-- | net/tnftp/files/src/main.c | 136 | ||||
-rw-r--r-- | net/tnftp/files/src/progressbar.c | 80 | ||||
-rw-r--r-- | net/tnftp/files/src/progressbar.h | 8 | ||||
-rw-r--r-- | net/tnftp/files/src/ruserpass.c | 94 | ||||
-rw-r--r-- | net/tnftp/files/src/util.c | 277 |
15 files changed, 1886 insertions, 974 deletions
diff --git a/net/tnftp/files/configure.ac b/net/tnftp/files/configure.ac new file mode 100644 index 00000000000..f9866530e07 --- /dev/null +++ b/net/tnftp/files/configure.ac @@ -0,0 +1,372 @@ +# $NetBSD: configure.ac,v 1.1.1.1 2007/08/06 04:42:53 lukem Exp $ +# +# Process this file with autoconf to produce a configure script. + +AC_INIT([tnftp], [20070806], [lukem@NetBSD.org]) +AC_PREREQ([2.61]) +AC_REVISION([$Revision: 1.1.1.1 $]) + +AS_SHELL_SANITIZE + +AC_CONFIG_SRCDIR([tnftp.h]) +AC_CONFIG_AUX_DIR(build-aux) +AC_CONFIG_HEADERS([config.h]) + +# +# Arguments for which features are included. +# +AC_CANONICAL_TARGET +AC_ARG_PROGRAM +AC_ARG_ENABLE([editcomplete], + [AS_HELP_STRING([--enable-editcomplete], + [turn on command line editing and completion. + (default: enabled)])], + [opt_editcomplete=$enableval], + [opt_editcomplete=yes]) +AC_ARG_ENABLE([ipv6], + [AS_HELP_STRING([--enable-ipv6], + [enable IPv6 support (if your OS supports it). + (default: enabled)])], + [opt_ipv6=$enableval], + [opt_ipv6=yes]) +AC_ARG_WITH([socks], + [AS_HELP_STRING([--with-socks], + [enable support for (Dante) SOCKS5 proxy])], + [], + [with_socks=check]) + +# +# Autoheader templates symbols. +# +AH_TEMPLATE([HAVE_POLL], + [Define if we have poll() and it is not emulated.]) +AH_TEMPLATE([HAVE_PRINTF_QD], + [Define if *printf() uses %qd to print `long long' + (otherwise uses %lld).]) +AH_TEMPLATE([HAVE_PRINTF_LONG_LONG], + [Define if `long long' is supported and + *printf() supports %lld or %qd to print them.]) +AH_TEMPLATE([USE_SOCKS], + [Define if using (Dante) SOCKS5 proxy.]) + +# +# Checks for programs. +# +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_AWK +AC_PROG_INSTALL +AC_CHECK_TOOL([AR], [ar], [:]) +AC_CHECK_TOOL([RANLIB], [ranlib], [:]) + +# +# Checks for tool features. +# +AS_CASE([$target_os], + [darwin*], + [# Mac OS X linker needs -search_paths_first so our private libraries + # are used before system libraries. + # + old_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -Wl,-search_paths_first" + AC_MSG_CHECKING([if ld accepts -search_paths_first]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[int i;]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + LDFLAGS=$old_LDFLAGS])], + ) + +# +# Checks for libraries. +# +AS_IF([test "$opt_editcomplete" = yes], + [AC_SEARCH_LIBS([tgetent], + [termcap termlib curses ncurses tinfo], + [], + [AC_MSG_ERROR( + [no relevant library found containing tgetent])]) + AC_SEARCH_LIBS([el_init], + [edit], + [have_libedit=yes], [have_libedit=no])]) + +AC_SEARCH_LIBS([gethostbyname], [nsl]) +AC_SEARCH_LIBS([socket], + [socket], + [], + [AC_CHECK_LIB([socket], + [socket], + [LIBS="-lsocket -lnsl $LIBS"], + [], + [-lnsl])]) + +# Check for (Dante) SOCKS5. +# +AS_IF([test "$with_socks" != no], + [AC_SEARCH_LIBS([SOCKSinit], + [socksd socks], + [AC_DEFINE([USE_SOCKS], [1]) + AS_IF([test "$opt_ipv6" = yes], + [AC_MSG_WARN( + [IPv6 is incompatible with socks, disabling IPv6 support]) + opt_ipv6=no])], + [AS_IF([test "$with_socks" != check], + [AC_MSG_FAILURE( + [--with-socks was given, but SOCKSinit() wasn't found])])])]) + +# +# Checks for header files. +# +accheck_includes=' +#include <stdio.h> +#if defined(HAVE_SYS_TYPES_H) +# include <sys/types.h> +#endif +#if defined(HAVE_SYS_STAT_H) +# include <sys/stat.h> +#endif +#if defined(STDC_HEADERS) +# include <stdarg.h> +# include <stdlib.h> +# include <string.h> +#endif +#if defined(HAVE_LIBGEN_H) +# include <libgen.h> +#endif +#if defined(HAVE_PWD_H) +# include <pwd.h> +#endif +#if defined(HAVE_UNISTD_H) +# include <unistd.h> +#endif +#if defined(HAVE_POLL_H) +# include <poll.h> +#elif defined(HAVE_SYS_POLL_H) +# include <sys/poll.h> +#endif +#if defined(HAVE_SYS_SOCKET_H) +# include <sys/socket.h> +#endif +#if defined(HAVE_NETINET_IN_H) +# include <netinet/in.h> +#endif +#if defined(HAVE_NETINET_IN_SYSTM_H) +# include <netinet/in_systm.h> +#endif +#if defined(HAVE_NETDB_H) +# include <netdb.h> +#endif +#if defined(HAVE_ARPA_INET_H) +# include <arpa/inet.h> +#endif +#if defined(HAVE_DIRENT_H) +# include <dirent.h> +#else +# define dirent direct +# if defined(HAVE_SYS_NDIR_H) +# include <sys/ndir.h> +# endif +# if defined(HAVE_SYS_DIR_H) +# include <sys/dir.h> +# endif +# if defined(HAVE_NDIR_H) +# include <ndir.h> +# endif +#endif +' # accheck_includes + +AC_CHECK_HEADERS([sys/types.h sys/ioctl.h sys/param.h sys/stat.h \ + sys/socket.h sys/syslimits.h sys/time.h sys/wait.h], + [], [], [$accheck_includes]) +AC_HEADER_DIRENT +AC_HEADER_RESOLV +AC_HEADER_STAT +AC_HEADER_STDC +AC_HEADER_TIME +AC_HEADER_TIOCGWINSZ +AC_CHECK_HEADERS([arpa/ftp.h arpa/inet.h arpa/nameser.h err.h \ + fcntl.h libgen.h limits.h malloc.h \ + netinet/in.h netinet/in_systm.h netinet/ip.h \ + paths.h poll.h pwd.h sys/poll.h regex.h \ + setjmp.h signal.h stddef.h termcap.h termios.h \ + unistd.h utime.h vis.h], + [], [], [$accheck_includes]) + +# +# Checks for typedefs, structures, and compiler characteristics. +# +AC_CHECK_DECLS([AI_NUMERICHOST, dirname, fclose, getpass, h_errno, pclose, + optarg, optind], + [], [], [$accheck_includes]) +AC_TYPE_LONG_DOUBLE +AC_TYPE_LONG_LONG_INT +AC_TYPE_UINT32_T +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_SIGNAL +AC_TYPE_SIZE_T +AC_STRUCT_TM +AC_CHECK_MEMBERS([struct sockaddr.sa_len, struct sockaddr_in.sin_len, + struct dirent.d_namlen], + [], [], [$accheck_includes]) +AC_CHECK_TYPES([in_port_t, sa_family_t, socklen_t, struct addrinfo], + [], [], [$accheck_includes]) +AC_SYS_LARGEFILE + +# If IPv6 is enabled, check for necessary items. +# +AS_IF([test "$opt_ipv6" = yes], + [AC_CHECK_DECLS([AF_INET6, NS_IN6ADDRSZ], [], [], +[$accheck_includes +#if defined(HAVE_ARPA_NAMESER_H) +#include <arpa/nameser.h> +#endif +]) + AC_CHECK_TYPES([struct sockaddr_in6], [], [], [$accheck_includes])]) + +# +# Checks for library functions. +# +#XXX remove alloca use +AC_FUNC_ALLOCA +AC_FUNC_CLOSEDIR_VOID +AC_FUNC_FORK +AC_FUNC_FSEEKO +AC_FUNC_STRCOLL +AC_REPLACE_FUNCS([dirname err fgetln getaddrinfo getnameinfo \ + inet_ntop inet_pton mkstemp setprogname sl_init snprintf \ + strdup strerror strlcat strlcpy strptime strsep strunvis \ + strvis timegm usleep utimes]) +AC_CHECK_FUNCS([getcwd gethostbyaddr gethostbyname gethostbyname2 gethostname \ + getpass getpassphrase getpgrp gettimeofday isascii \ + memchr memmove memset realpath regcomp \ + select setlocale socket strcasecmp strchr strcspn strdup \ + strerror strncasecmp strpbrk strrchr strstr strtol strtoul \ + utime]) +AS_IF([test "$ac_cv_func_getpgrp" = yes], [AC_FUNC_GETPGRP]) +AS_IF([test "$ac_cv_func_strptime" = yes], [AC_CHECK_DECLS([strptime])]) + +# Always replace glob(); the vendor's may not be secure. +# +AC_LIBOBJ([glob]) + +# We assume that if sprintf() supports %lld or %qd, +# then all of *printf() does. If not, disable long long +# support because we don't know how to display it. +# +AS_IF([test "$ac_cv_type_long_long_int" = yes], + [AC_MSG_CHECKING([*printf() support for %lld]) + can_printf_longlong=no + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include <stdio.h> +int main() { + char buf[100]; + sprintf(buf, "%lld", 4294967300LL); + return (strcmp(buf, "4294967300")); +} +]])], + [AC_MSG_RESULT([yes]) + can_printf_longlong=yes], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([unknown - cross-compiling])]) + AS_IF([test "$can_printf_longlong" != yes], + [AC_MSG_CHECKING([*printf() support for %qd]) + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include <stdio.h> +int main() { + char buf[100]; + sprintf(buf, "%qd", 4294967300LL); + return (strcmp(buf, "4294967300")); +} +]])], + [AC_MSG_RESULT([yes]) + can_printf_longlong=yes + AC_DEFINE([HAVE_PRINTF_QD], [1])], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([unknown - cross-compiling])])]) + AC_MSG_CHECKING([if *printf() can print long long ints]) + AS_IF([test "$can_printf_longlong" = yes], + [AC_MSG_RESULT([yes]) + AC_DEFINE([HAVE_PRINTF_LONG_LONG], [1]) + AC_REPLACE_FUNCS([strtoll])], + [AC_MSG_RESULT([no])])]) + +# Handle Darwin 7 having a poll() compatibility function, +# and don't use it if it's emulated. +# Be conservative, if we don't find one of poll.h or sys/poll.h, +# don't attempt to use poll(). +# +AC_CHECK_TYPES([struct pollfd], [], [], [$accheck_includes]) +AC_CHECK_FUNC([poll], + [AC_CHECK_DECL([_POLL_EMUL_H_], + [], + [AC_DEFINE([HAVE_POLL], [1])], + [$accheck_includes])]) + +# Assume libedit is not up-to-date and force own version. +# +have_libedit=no +AS_IF([test "$opt_editcomplete" = yes], + [AC_MSG_CHECKING([for up-to-date libedit]) + AS_IF([test "$have_libedit" = no], + [AC_MSG_RESULT([no - using my own]) + INCLUDES="-I\${srcdir}/../libedit $INCLUDES" + LDFLAGS="-L../libedit $LDFLAGS" + LIBS="-ledit $LIBS" + LIBEDIT=libedit.a + LIBDEPENDS="$LIBDEPENDS ../libedit/libedit.a"], + [AC_MSG_RESULT([yes])])], + [CFLAGS="-DNO_EDITCOMPLETE $CFLAGS"]) + +# Replace sl_init() (et al) if it provides the older API. +# +AS_IF([test "$ac_cv_func_sl_init" = yes], + [AC_MSG_CHECKING([if sl_add() returns int]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stringlist.h>]], + [[int f = sl_add((StringList *)0, + "foo");]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no - using local version]) + AC_LIBOBJ([sl_init])], + [AC_MSG_RESULT([unknown - cross-compiling])])]) + +# Replace getaddrinfo() if missing or AI_NUMERICHOST isn't declared. +# +AC_MSG_CHECKING([for working getaddrinfo()]) +AS_IF([test "$ac_cv_have_decl_AI_NUMERICHOST" = yes], + [AC_MSG_RESULT([yes])], + [AS_IF([test "$ac_cv_func_getaddrinfo" = yes], + [AC_LIBOBJ([getaddrinfo]) + AC_MSG_RESULT([no - using local version])], + [AC_MSG_RESULT([using local version])])]) + +# Check for VIS_WHITE in <vis.h> +# +AS_IF([test "$ac_cv_header_vis_h" = yes], + [AC_CHECK_DECL([VIS_WHITE], [], [], [ +#include <vis.h> +])]) + +# Build libnetbsd if necessary. +# +AS_IF([test -n "$LIBOBJS"], + [INCLUDES="$INCLUDES -I\${srcdir}/../libnetbsd" + LDFLAGS="$LDFLAGS -L../libnetbsd" + LIBS="$LIBS -lnetbsd" + LIBNETBSD=libnetbsd.a + LIBDEPENDS="$LIBDEPENDS ../libnetbsd/libnetbsd.a"]) + +# +# Create the Makefiles. +# +AC_SUBST(INCLUDES) +AC_SUBST(LIBEDIT) +AC_SUBST(LIBNETBSD) +AC_SUBST(LIBDEPENDS) + +AC_CONFIG_FILES([Makefile + libedit/Makefile + libedit/makelist + libnetbsd/Makefile + src/Makefile]) + +AC_OUTPUT diff --git a/net/tnftp/files/src/cmds.c b/net/tnftp/files/src/cmds.c index d9a99d28149..b5ad5e069f5 100644 --- a/net/tnftp/files/src/cmds.c +++ b/net/tnftp/files/src/cmds.c @@ -1,8 +1,8 @@ -/* NetBSD: cmds.c,v 1.9 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: cmds.c,v 1.115 2005/06/10 00:18:46 lukem Exp */ +/* $NetBSD: cmds.c,v 1.1.1.5 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: cmds.c,v 1.123 2007/05/24 05:05:18 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,16 +99,46 @@ * SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94"; +#else +__RCSID(" NetBSD: cmds.c,v 1.123 2007/05/24 05:05:18 lukem Exp "); +#endif +#endif /* not lint */ + /* * FTP User Program -- Command Routines. */ - -#include "tnftp.h" +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <arpa/ftp.h> + +#include <ctype.h> +#include <err.h> +#include <glob.h> +#include <limits.h> +#include <netdb.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#endif /* tnftp */ #include "ftp_var.h" #include "version.h" -struct types { +static struct types { char *t_name; char *t_mode; int t_type; @@ -122,30 +152,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)) { @@ -160,7 +203,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); @@ -193,7 +236,7 @@ settype(int argc, char *argv[]) if (argc == 0 || argc > 2) { char *sep; - fprintf(ttyout, "usage: %s [", argv[0]); + UPRINTF("usage: %s [", argv[0]); sep = " "; for (p = types; p->t_name; p++) { fprintf(ttyout, "%s%s", sep, p->t_name); @@ -241,14 +284,13 @@ changetype(int newtype, int show) newtype = TYPE_I; if (newtype == curtype) return; - if (debug == 0 && show == 0) + if (ftp_debug == 0 && show == 0) verbose = 0; for (p = types; p->t_name; p++) 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); @@ -274,7 +316,7 @@ setbinary(int argc, char *argv[]) { if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -291,7 +333,7 @@ setascii(int argc, char *argv[]) { if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -308,7 +350,7 @@ settenex(int argc, char *argv[]) { if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -325,7 +367,7 @@ setftmode(int argc, char *argv[]) { if (argc != 2) { - fprintf(ttyout, "usage: %s mode-name\n", argv[0]); + UPRINTF("usage: %s mode-name\n", argv[0]); code = -1; return; } @@ -342,7 +384,7 @@ setform(int argc, char *argv[]) { if (argc != 2) { - fprintf(ttyout, "usage: %s format\n", argv[0]); + UPRINTF("usage: %s format\n", argv[0]); code = -1; return; } @@ -359,7 +401,7 @@ setstruct(int argc, char *argv[]) { if (argc != 2) { - fprintf(ttyout, "usage: %s struct-mode\n", argv[0]); + UPRINTF("usage: %s struct-mode\n", argv[0]); code = -1; return; } @@ -388,8 +430,7 @@ put(int argc, char *argv[]) goto usage; if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) { usage: - fprintf(ttyout, "usage: %s local-file [remote-file]\n", - argv[0]); + UPRINTF("usage: %s local-file [remote-file]\n", argv[0]); code = -1; return; } @@ -433,15 +474,14 @@ mput(int argc, char *argv[]) const char *tp; if (argc == 0 || (argc == 1 && !another(&argc, &argv, "local-files"))) { - fprintf(ttyout, "usage: %s local-files\n", argv[0]); + UPRINTF("usage: %s local-files\n", argv[0]); code = -1; return; } - mname = argv[0]; mflag = 1; oldintr = xsignal(SIGINT, mintr); if (sigsetjmp(jabort, 1)) - mabort(); + mabort(argv[0]); if (proxy) { char *cp; @@ -459,7 +499,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; @@ -483,7 +523,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; @@ -495,7 +535,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; } @@ -511,7 +551,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; @@ -562,8 +602,7 @@ getit(int argc, char *argv[], int restartit, const char *mode) goto usage; if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) { usage: - fprintf(ttyout, "usage: %s remote-file [local-file]\n", - argv[0]); + UPRINTF("usage: %s remote-file [local-file]\n", argv[0]); code = -1; return (0); } @@ -586,7 +625,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; @@ -614,7 +653,7 @@ getit(int argc, char *argv[], int restartit, const char *mode) } /* ARGSUSED */ -void +static void mintr(int signo) { @@ -624,8 +663,8 @@ mintr(int signo) siglongjmp(jabort, 1); } -void -mabort(void) +static void +mabort(const char *cmd) { int ointer, oconf; @@ -634,7 +673,7 @@ mabort(void) oconf = confirmrest; interactive = 1; confirmrest = 0; - if (confirm("Continue with", mname)) { + if (confirm(cmd, NULL)) { interactive = ointer; confirmrest = oconf; return; @@ -659,11 +698,10 @@ mget(int argc, char *argv[]) if (argc == 0 || (argc == 1 && !another(&argc, &argv, "remote-files"))) { - fprintf(ttyout, "usage: %s remote-files\n", argv[0]); + UPRINTF("usage: %s remote-files\n", argv[0]); code = -1; return; } - mname = argv[0]; mflag = 1; restart_point = 0; restartit = 0; @@ -677,7 +715,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) { @@ -700,7 +738,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); @@ -708,7 +746,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; } @@ -723,18 +761,19 @@ mget(int argc, char *argv[]) void fget(int argc, char *argv[]) { - char *buf, *mode; + char *mode; FILE *fp; + char buf[MAXPATHLEN]; if (argc != 2) { - fprintf(ttyout, "usage: %s localfile\n", argv[0]); + UPRINTF("usage: %s localfile\n", argv[0]); code = -1; return; } 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; } @@ -742,9 +781,7 @@ fget(int argc, char *argv[]) argv[0] = "get"; mode = restart_point ? "r+" : "w"; - for (; - (buf = fparseln(fp, NULL, NULL, "\0\0\0", 0)) != NULL; - free(buf)) { + while (getline(fp, buf, sizeof(buf), NULL) >= 0) { if (buf[0] == '\0') continue; argv[1] = buf; @@ -769,7 +806,7 @@ status(int argc, char *argv[]) { if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -863,7 +900,7 @@ togglevar(int argc, char *argv[], int *var, const char *mesg) } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) { *var = 0; } else { - fprintf(ttyout, "usage: %s [ on | off ]\n", argv[0]); + UPRINTF("usage: %s [ on | off ]\n", argv[0]); return (-1); } if (mesg) @@ -892,7 +929,7 @@ setedit(int argc, char *argv[]) #ifdef NO_EDITCOMPLETE if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -926,7 +963,7 @@ sethash(int argc, char *argv[]) if (argc == 1) hash = !hash; else if (argc != 2) { - fprintf(ttyout, "usage: %s [ on | off | bytecount ]\n", + UPRINTF("usage: %s [ on | off | bytecount ]\n", argv[0]); code = -1; return; @@ -1012,7 +1049,7 @@ setgate(int argc, char *argv[]) static char gsbuf[MAXHOSTNAMELEN]; if (argc == 0 || argc > 3) { - fprintf(ttyout, + UPRINTF( "usage: %s [ on | off | gateserver [port] ]\n", argv[0]); code = -1; return; @@ -1025,7 +1062,7 @@ setgate(int argc, char *argv[]) gatemode = 0; else { if (argc == 3) - gateport = xstrdup(argv[2]); + gateport = ftp_strdup(argv[2]); (void)strlcpy(gsbuf, argv[1], sizeof(gsbuf)); gateserver = gsbuf; gatemode = 1; @@ -1073,15 +1110,14 @@ void setdebug(int argc, char *argv[]) { if (argc == 0 || argc > 2) { - fprintf(ttyout, "usage: %s [ on | off | debuglevel ]\n", - argv[0]); + UPRINTF("usage: %s [ on | off | debuglevel ]\n", argv[0]); code = -1; return; } else if (argc == 2) { if (strcasecmp(argv[1], "on") == 0) - debug = 1; + ftp_debug = 1; else if (strcasecmp(argv[1], "off") == 0) - debug = 0; + ftp_debug = 0; else { int val; @@ -1092,16 +1128,16 @@ setdebug(int argc, char *argv[]) code = -1; return; } - debug = val; + ftp_debug = val; } } else - debug = !debug; - if (debug) + ftp_debug = !ftp_debug; + if (ftp_debug) options |= SO_DEBUG; else options &= ~SO_DEBUG; - fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug); - code = debug > 0; + fprintf(ttyout, "Debugging %s (ftp_debug=%d).\n", onoff(ftp_debug), ftp_debug); + code = ftp_debug > 0; } /* @@ -1114,7 +1150,7 @@ cd(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "remote-directory"))) { - fprintf(ttyout, "usage: %s remote-directory\n", argv[0]); + UPRINTF("usage: %s remote-directory\n", argv[0]); code = -1; return; } @@ -1145,13 +1181,13 @@ lcd(int argc, char *argv[]) argv[1] = localhome; } if (argc != 2) { - fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]); + UPRINTF("usage: %s [local-directory]\n", argv[0]); return; } 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]) { @@ -1173,7 +1209,7 @@ delete(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "remote-file"))) { - fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + UPRINTF("usage: %s remote-file\n", argv[0]); code = -1; return; } @@ -1193,15 +1229,14 @@ mdelete(int argc, char *argv[]) if (argc == 0 || (argc == 1 && !another(&argc, &argv, "remote-files"))) { - fprintf(ttyout, "usage: %s [remote-files]\n", argv[0]); + UPRINTF("usage: %s [remote-files]\n", argv[0]); 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; @@ -1213,7 +1248,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; @@ -1235,7 +1270,7 @@ renamefile(int argc, char *argv[]) goto usage; if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) { usage: - fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]); + UPRINTF("usage: %s from-name to-name\n", argv[0]); code = -1; return; } @@ -1296,11 +1331,9 @@ ls(int argc, char *argv[]) if (argc > 3 || ((pagecmd | mlsdcmd) && argc > 2)) { usage: if (pagecmd || mlsdcmd) - fprintf(ttyout, - "usage: %s [remote-path]\n", argv[0]); + UPRINTF("usage: %s [remote-path]\n", argv[0]); else - fprintf(ttyout, - "usage: %s [remote-path [local-file]]\n", + UPRINTF("usage: %s [remote-path [local-file]]\n", argv[0]); code = -1; goto freels; @@ -1314,12 +1347,11 @@ ls(int argc, char *argv[]) if (EMPTYSTRING(p)) p = DEFAULTPAGER; len = strlen(p) + 2; - locfile = xmalloc(len); + locfile = ftp_malloc(len); locfile[0] = '|'; (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; @@ -1350,13 +1382,12 @@ mls(int argc, char *argv[]) goto usage; if (argc < 3 && !another(&argc, &argv, "local-file")) { usage: - fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]); + UPRINTF("usage: %s remote-files local-file\n", argv[0]); code = -1; return; } 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)) { @@ -1367,7 +1398,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, @@ -1375,7 +1406,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; @@ -1400,7 +1431,7 @@ shell(int argc, char *argv[]) int wait_status; if (argc == 0) { - fprintf(ttyout, "usage: %s [command [args]]\n", argv[0]); + UPRINTF("usage: %s [command [args]]\n", argv[0]); code = -1; return; } @@ -1418,7 +1449,7 @@ shell(int argc, char *argv[]) else namep++; (void)strlcpy(shellnam, namep, sizeof(shellnam)); - if (debug) { + if (ftp_debug) { fputs(shell, ttyout); putc('\n', ttyout); } @@ -1428,7 +1459,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); } @@ -1437,7 +1468,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; @@ -1450,6 +1481,7 @@ void user(int argc, char *argv[]) { char *password; + char emptypass[] = ""; int n, aflag = 0; if (argc == 0) @@ -1458,7 +1490,7 @@ user(int argc, char *argv[]) (void)another(&argc, &argv, "username"); if (argc < 2 || argc > 4) { usage: - fprintf(ttyout, "usage: %s username [password [account]]\n", + UPRINTF("usage: %s username [password [account]]\n", argv[0]); code = -1; return; @@ -1467,6 +1499,8 @@ user(int argc, char *argv[]) if (n == CONTINUE) { if (argc < 3) { password = getpass("Password: "); + if (password == NULL) + password = emptypass; } else { password = argv[2]; } @@ -1477,6 +1511,8 @@ user(int argc, char *argv[]) aflag++; if (argc < 4) { password = getpass("Account: "); + if (password == NULL) + password = emptypass; } else { password = argv[3]; } @@ -1506,7 +1542,7 @@ pwd(int argc, char *argv[]) code = -1; if (argc != 1) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); return; } if (! remotecwd[0]) @@ -1528,7 +1564,7 @@ lpwd(int argc, char *argv[]) code = -1; if (argc != 1) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); return; } if (! localcwd[0]) @@ -1551,7 +1587,7 @@ makedir(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "directory-name"))) { - fprintf(ttyout, "usage: %s directory-name\n", argv[0]); + UPRINTF("usage: %s directory-name\n", argv[0]); code = -1; return; } @@ -1576,7 +1612,7 @@ removedir(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "directory-name"))) { - fprintf(ttyout, "usage: %s directory-name\n", argv[0]); + UPRINTF("usage: %s directory-name\n", argv[0]); code = -1; return; } @@ -1600,7 +1636,7 @@ quote(int argc, char *argv[]) if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command line to send"))) { - fprintf(ttyout, "usage: %s line-to-send\n", argv[0]); + UPRINTF("usage: %s line-to-send\n", argv[0]); code = -1; return; } @@ -1618,7 +1654,7 @@ site(int argc, char *argv[]) if (argc == 0 || (argc == 1 && !another(&argc, &argv, "arguments to SITE command"))){ - fprintf(ttyout, "usage: %s line-to-send\n", argv[0]); + UPRINTF("usage: %s line-to-send\n", argv[0]); code = -1; return; } @@ -1656,7 +1692,7 @@ do_chmod(int argc, char *argv[]) goto usage; if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) { usage: - fprintf(ttyout, "usage: %s mode remote-file\n", argv[0]); + UPRINTF("usage: %s mode remote-file\n", argv[0]); code = -1; return; } @@ -1675,7 +1711,7 @@ do_umask(int argc, char *argv[]) int oldverbose = verbose; if (argc == 0) { - fprintf(ttyout, "usage: %s [umask]\n", argv[0]); + UPRINTF("usage: %s [umask]\n", argv[0]); code = -1; return; } @@ -1690,7 +1726,7 @@ idlecmd(int argc, char *argv[]) int oldverbose = verbose; if (argc < 1 || argc > 2) { - fprintf(ttyout, "usage: %s [seconds]\n", argv[0]); + UPRINTF("usage: %s [seconds]\n", argv[0]); code = -1; return; } @@ -1708,7 +1744,7 @@ rmthelp(int argc, char *argv[]) int oldverbose = verbose; if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -1728,7 +1764,7 @@ quit(int argc, char *argv[]) /* this may be called with argc == 0, argv == NULL */ if (argc == 0 && argv != NULL) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -1750,7 +1786,7 @@ disconnect(int argc, char *argv[]) /* this may be called with argc == 0, argv == NULL */ if (argc == 0 && argv != NULL) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -1764,17 +1800,22 @@ void account(int argc, char *argv[]) { char *ap; + char emptypass[] = ""; if (argc == 0 || argc > 2) { - fprintf(ttyout, "usage: %s [password]\n", argv[0]); + UPRINTF("usage: %s [password]\n", argv[0]); code = -1; return; } 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; @@ -1806,7 +1847,7 @@ doproxy(int argc, char *argv[]) sigfunc oldintr; if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) { - fprintf(ttyout, "usage: %s command\n", argv[0]); + UPRINTF("usage: %s command\n", argv[0]); code = -1; return; } @@ -1898,7 +1939,7 @@ setntrans(int argc, char *argv[]) { if (argc == 0 || argc > 3) { - fprintf(ttyout, "usage: %s [inchars [outchars]]\n", argv[0]); + UPRINTF("usage: %s [inchars [outchars]]\n", argv[0]); code = -1; return; } @@ -1962,7 +2003,7 @@ setnmap(int argc, char *argv[]) } if (argc == 0 || (argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) { - fprintf(ttyout, "usage: %s [mapin mapout]\n", argv[0]); + UPRINTF("usage: %s [mapin mapout]\n", argv[0]); code = -1; return; } @@ -2162,7 +2203,7 @@ setpassive(int argc, char *argv[]) activefallback = passivemode; } else if (argc != 2) { passiveusage: - fprintf(ttyout, "usage: %s [ on | off | auto ]\n", argv[0]); + UPRINTF("usage: %s [ on | off | auto ]\n", argv[0]); code = -1; return; } else if (strcasecmp(argv[1], "on") == 0) { @@ -2213,11 +2254,11 @@ parserate(int argc, char *argv[], int cmdlineopt) if (argc > 4 || (argc < (cmdlineopt ? 3 : 2))) { usage: if (cmdlineopt) - fprintf(ttyout, + UPRINTF( "usage: %s (all|get|put),maximum-bytes[,increment-bytes]]\n", argv[0]); else - fprintf(ttyout, + UPRINTF( "usage: %s (all|get|put) [maximum-bytes [increment-bytes]]\n", argv[0]); return -1; @@ -2289,7 +2330,7 @@ cdup(int argc, char *argv[]) int r; if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -2314,7 +2355,7 @@ restart(int argc, char *argv[]) { if (argc == 0 || argc > 2) { - fprintf(ttyout, "usage: %s [restart-point]\n", argv[0]); + UPRINTF("usage: %s [restart-point]\n", argv[0]); code = -1; return; } @@ -2351,7 +2392,7 @@ syst(int argc, char *argv[]) int oldverbose = verbose; if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -2376,7 +2417,7 @@ macdef(int argc, char *argv[]) } if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) { usage: - fprintf(ttyout, "usage: %s macro_name\n", argv[0]); + UPRINTF("usage: %s macro_name\n", argv[0]); code = -1; return; } @@ -2434,7 +2475,7 @@ sizecmd(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "remote-file"))) { - fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + UPRINTF("usage: %s remote-file\n", argv[0]); code = -1; return; } @@ -2455,13 +2496,14 @@ modtime(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "remote-file"))) { - fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + UPRINTF("usage: %s remote-file\n", argv[0]); code = -1; return; } mtime = remotemodtime(argv[1], 1); if (mtime != -1) - fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime))); + fprintf(ttyout, "%s\t%s", argv[1], + rfc2822time(localtime(&mtime))); code = (mtime > 0); } @@ -2473,7 +2515,7 @@ rmtstatus(int argc, char *argv[]) { if (argc == 0) { - fprintf(ttyout, "usage: %s [remote-file]\n", argv[0]); + UPRINTF("usage: %s [remote-file]\n", argv[0]); code = -1; return; } @@ -2504,7 +2546,7 @@ lpage(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "local-file"))) { - fprintf(ttyout, "usage: %s local-file\n", argv[0]); + UPRINTF("usage: %s local-file\n", argv[0]); code = -1; return; } @@ -2516,7 +2558,7 @@ lpage(int argc, char *argv[]) if (EMPTYSTRING(p)) p = DEFAULTPAGER; len = strlen(p) + strlen(locfile) + 2; - pager = xmalloc(len); + pager = ftp_malloc(len); (void)strlcpy(pager, p, len); (void)strlcat(pager, " ", len); (void)strlcat(pager, locfile, len); @@ -2538,7 +2580,7 @@ page(int argc, char *argv[]) if (argc == 0 || argc > 2 || (argc == 1 && !another(&argc, &argv, "remote-file"))) { - fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + UPRINTF("usage: %s remote-file\n", argv[0]); code = -1; return; } @@ -2546,7 +2588,7 @@ page(int argc, char *argv[]) if (EMPTYSTRING(p)) p = DEFAULTPAGER; len = strlen(p) + 2; - pager = xmalloc(len); + pager = ftp_malloc(len); pager[0] = '|'; (void)strlcpy(pager + 1, p, len - 1); @@ -2571,7 +2613,7 @@ setxferbuf(int argc, char *argv[]) if (argc != 2) { usage: - fprintf(ttyout, "usage: %s size\n", argv[0]); + UPRINTF("usage: %s size\n", argv[0]); code = -1; return; } @@ -2611,7 +2653,7 @@ setoption(int argc, char *argv[]) code = -1; if (argc == 0 || (argc != 1 && argc != 3)) { - fprintf(ttyout, "usage: %s [option value]\n", argv[0]); + UPRINTF("usage: %s [option value]\n", argv[0]); return; } @@ -2628,7 +2670,7 @@ setoption(int argc, char *argv[]) return; } FREEPTR(o->value); - o->value = xstrdup(argv[2]); + o->value = ftp_strdup(argv[2]); if (verbose) fprintf(ttyout, "Setting `%s' to `%s'.\n", o->name, o->value); @@ -2646,7 +2688,7 @@ unsetoption(int argc, char *argv[]) code = -1; if (argc == 0 || argc != 2) { - fprintf(ttyout, "usage: %s option\n", argv[0]); + UPRINTF("usage: %s option\n", argv[0]); return; } @@ -2669,7 +2711,7 @@ feat(int argc, char *argv[]) int oldverbose = verbose; if (argc == 0) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } @@ -2689,7 +2731,7 @@ mlst(int argc, char *argv[]) int oldverbose = verbose; if (argc < 1 || argc > 2) { - fprintf(ttyout, "usage: %s [remote-path]\n", argv[0]); + UPRINTF("usage: %s [remote-path]\n", argv[0]); code = -1; return; } @@ -2709,7 +2751,7 @@ opts(int argc, char *argv[]) int oldverbose = verbose; if (argc < 2 || argc > 3) { - fprintf(ttyout, "usage: %s command [options]\n", argv[0]); + UPRINTF("usage: %s command [options]\n", argv[0]); code = -1; return; } diff --git a/net/tnftp/files/src/cmdtab.c b/net/tnftp/files/src/cmdtab.c index e065f5cb2b4..756088f9962 100644 --- a/net/tnftp/files/src/cmdtab.c +++ b/net/tnftp/files/src/cmdtab.c @@ -1,5 +1,5 @@ -/* NetBSD: cmdtab.c,v 1.7 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: cmdtab.c,v 1.45 2005/06/09 16:38:29 lukem Exp */ +/* $NetBSD: cmdtab.c,v 1.1.1.5 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: cmdtab.c,v 1.47 2007/04/11 04:40:19 lukem Exp */ /*- * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. @@ -68,6 +68,21 @@ #include "tnftp.h" +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94"; +#else +__RCSID(" NetBSD: cmdtab.c,v 1.47 2007/04/11 04:40:19 lukem Exp "); +#endif +#endif /* not lint */ + +#include <stdio.h> + +#endif /* tnftp */ + #include "ftp_var.h" /* diff --git a/net/tnftp/files/src/complete.c b/net/tnftp/files/src/complete.c index 5dd7ed19b8d..ee0ecef6769 100644 --- a/net/tnftp/files/src/complete.c +++ b/net/tnftp/files/src/complete.c @@ -1,5 +1,5 @@ -/* NetBSD: complete.c,v 1.6 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: complete.c,v 1.40 2005/06/09 16:38:29 lukem Exp */ +/* $NetBSD: complete.c,v 1.1.1.4 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: complete.c,v 1.42 2007/04/17 05:52:03 lukem Exp */ /*- * Copyright (c) 1997-2000,2005 The NetBSD Foundation, Inc. @@ -37,11 +37,29 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID(" NetBSD: complete.c,v 1.42 2007/04/17 05:52:03 lukem Exp "); +#endif /* not lint */ + /* * FTP user program - command and file completion routines */ -#include "tnftp.h" +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#endif /* tnftp */ #include "ftp_var.h" @@ -132,14 +150,14 @@ complete_command(char *word, int list) size_t wordlen; unsigned char rv; - words = xsl_init(); + words = ftp_sl_init(); wordlen = strlen(word); for (c = cmdtab; c->c_name != NULL; c++) { if (wordlen > strlen(c->c_name)) continue; if (strncmp(word, c->c_name, wordlen) == 0) - xsl_add(words, c->c_name); + ftp_sl_add(words, c->c_name); } rv = complete_ambiguous(word, list, words); @@ -189,7 +207,7 @@ complete_local(char *word, int list) if ((dd = opendir(dir)) == NULL) return (CC_ERROR); - words = xsl_init(); + words = ftp_sl_init(); len = strlen(file); for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { @@ -206,8 +224,8 @@ complete_local(char *word, int list) if (strncmp(file, dp->d_name, len) == 0) { char *tcp; - tcp = xstrdup(dp->d_name); - xsl_add(words, tcp); + tcp = ftp_strdup(dp->d_name); + ftp_sl_add(words, tcp); } } closedir(dd); @@ -244,14 +262,14 @@ complete_option(char *word, int list) size_t wordlen; unsigned char rv; - words = xsl_init(); + words = ftp_sl_init(); wordlen = strlen(word); for (o = optiontab; o->name != NULL; o++) { if (wordlen > strlen(o->name)) continue; if (strncmp(word, o->name, wordlen) == 0) - xsl_add(words, o->name); + ftp_sl_add(words, o->name); } rv = complete_ambiguous(word, list, words); @@ -297,7 +315,7 @@ complete_remote(char *word, int list) if (dirlist != NULL) sl_free(dirlist, 1); - dirlist = xsl_init(); + dirlist = ftp_sl_init(); mflag = 1; emesg = NULL; @@ -315,8 +333,8 @@ complete_remote(char *word, int list) tcp++; else tcp = cp; - tcp = xstrdup(tcp); - xsl_add(dirlist, tcp); + tcp = ftp_strdup(tcp); + ftp_sl_add(dirlist, tcp); } if (emesg != NULL) { fprintf(ttyout, "\n%s\n", emesg); @@ -326,13 +344,13 @@ complete_remote(char *word, int list) dirchange = 0; } - words = xsl_init(); + words = ftp_sl_init(); for (i = 0; i < dirlist->sl_cur; i++) { cp = dirlist->sl_str[i]; if (strlen(file) > strlen(cp)) continue; if (strncmp(file, cp, strlen(file)) == 0) - xsl_add(words, cp); + ftp_sl_add(words, cp); } rv = complete_ambiguous(file, list, words); sl_free(words, 0); @@ -415,7 +433,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/net/tnftp/files/src/domacro.c b/net/tnftp/files/src/domacro.c index 001df2e2a91..916abf33108 100644 --- a/net/tnftp/files/src/domacro.c +++ b/net/tnftp/files/src/domacro.c @@ -1,5 +1,5 @@ -/* NetBSD: domacro.c,v 1.5 2005/06/09 16:47:50 lukem Exp */ -/* from NetBSD: domacro.c,v 1.20 2003/08/07 11:13:53 agc Exp */ +/* $NetBSD: domacro.c,v 1.1.1.5 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: domacro.c,v 1.21 2005/06/29 02:31:19 christos Exp */ /* * Copyright (c) 1985, 1993, 1994 @@ -32,6 +32,23 @@ #include "tnftp.h" +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID(" NetBSD: domacro.c,v 1.21 2005/06/29 02:31:19 christos Exp "); +#endif +#endif /* not lint */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +#endif /* tnftp */ + #include "ftp_var.h" void @@ -43,7 +60,7 @@ domacro(int argc, char *argv[]) if ((argc == 0 && argv != NULL) || (argc < 2 && !another(&argc, &argv, "macro name"))) { - fprintf(ttyout, "usage: %s macro_name [args]\n", argv[0]); + UPRINTF("usage: %s macro_name [args]\n", argv[0]); code = -1; return; } diff --git a/net/tnftp/files/src/fetch.c b/net/tnftp/files/src/fetch.c index 2a8f1fdff3e..13b5a10b820 100644 --- a/net/tnftp/files/src/fetch.c +++ b/net/tnftp/files/src/fetch.c @@ -1,8 +1,8 @@ -/* NetBSD: fetch.c,v 1.11 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: fetch.c,v 1.162 2005/06/10 00:18:46 lukem Exp */ +/* $NetBSD: fetch.c,v 1.1.1.5 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: fetch.c,v 1.180 2007/06/05 00:31:20 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 @@ -40,11 +40,42 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID(" NetBSD: fetch.c,v 1.180 2007/06/05 00:31:20 lukem Exp "); +#endif /* not lint */ + /* * FTP User Program -- Command line file retrieval */ -#include "tnftp.h" +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <netinet/in.h> + +#include <arpa/ftp.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> + +#endif /* tnftp */ #include "ftp_var.h" #include "version.h" @@ -88,7 +119,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 * @@ -134,11 +165,10 @@ auth_url(const char *challenge, char **response, const char *guser, cp = challenge; scheme = "Basic"; /* only support Basic authentication */ - if (debug) - fprintf(ttyout, "auth_url: challenge `%s'\n", challenge); + 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; } @@ -147,7 +177,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; } @@ -155,10 +185,10 @@ auth_url(const char *challenge, char **response, const char *guser, if ((ep = strchr(cp, '\"')) != NULL) { size_t len = ep - cp; - realm = (char *)xmalloc(len + 1); + 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; } @@ -173,15 +203,19 @@ auth_url(const char *challenge, char **response, const char *guser, warnx("%s; can't authenticate", errormsg); goto cleanup_auth_url; } - user[strlen(user) - 1] = '\0'; } 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 *)xmalloc(clen); + clear = (char *)ftp_malloc(clen); (void)strlcpy(clear, user, clen); (void)strlcat(clear, ":", clen); (void)strlcat(clear, pass, clen); @@ -190,7 +224,7 @@ auth_url(const char *challenge, char **response, const char *guser, /* scheme + " " + enc + "\0" */ rlen = strlen(scheme) + 1 + (clen + 2) * 4 / 3 + 1; - *response = (char *)xmalloc(rlen); + *response = (char *)ftp_malloc(rlen); (void)strlcpy(*response, scheme, rlen); len = strlcat(*response, " ", rlen); /* use `clen - 1' to not encode the trailing NUL */ @@ -259,7 +293,7 @@ url_decode(char *url) /* - * Parse URL of form: + * Parse URL of form (per RFC3986): * <type>://[<user>[:<password>]@]<host>[:<port>][/<path>] * Returns -1 if a parse error occurred, otherwise 0. * It's the caller's responsibility to url_decode() the returned @@ -269,12 +303,9 @@ url_decode(char *url) * malloc(3)ed strings of the relevant section, and port to * the number given, or ftpport if ftp://, or httpport if http://. * - * If <host> is surrounded by `[' and ']', it's parsed as an - * IPv6 address (as per RFC 2732). - * - * XXX: this is not totally RFC 1738 compliant; <path> will have the + * XXX: this is not totally RFC3986 compliant; <path> will have the * leading `/' unless it's an ftp:// URL, as this makes things easier - * for file:// and http:// URLs. ftp:// URLs have the `/' between the + * for file:// and http:// URLs. ftp:// URLs have the `/' between the * host and the URL-path removed, but any additional leading slashes * in the URL-path are retained (because they imply that we should * later do "CWD" with a null argument). @@ -282,11 +313,14 @@ url_decode(char *url) * Examples: * input URL output path * --------- ----------- - * "ftp://host" NULL - * "http://host/" NULL + * "http://host" "/" + * "http://host/" "/" + * "http://host/path" "/path" * "file://host/dir/file" "dir/file" + * "ftp://host" "" * "ftp://host/" "" - * "ftp://host//" NULL + * "ftp://host//" "/" + * "ftp://host/dir/file" "dir/file" * "ftp://host//dir/file" "/dir/file" */ static int @@ -341,14 +375,14 @@ parse_url(const char *url, const char *desc, url_t *type, /* find [user[:pass]@]host[:port] */ ep = strchr(url, '/'); if (ep == NULL) - thost = xstrdup(url); + thost = ftp_strdup(url); else { len = ep - url; - thost = (char *)xmalloc(len + 1); + thost = (char *)ftp_malloc(len + 1); (void)strlcpy(thost, url, len + 1); if (*type == FTP_URL_T) /* skip first / for ftp URLs */ ep++; - *path = xstrdup(ep); + *path = ftp_strdup(ep); } cp = strchr(thost, '@'); /* look for user[:pass]@ in URLs */ @@ -357,11 +391,11 @@ parse_url(const char *url, const char *desc, url_t *type, anonftp = 0; /* disable anonftp */ *user = thost; *cp = '\0'; - thost = xstrdup(cp + 1); + thost = ftp_strdup(cp + 1); cp = strchr(*user, ':'); if (cp != NULL) { *cp = '\0'; - *pass = xstrdup(cp + 1); + *pass = ftp_strdup(cp + 1); } url_decode(*user); if (*pass) @@ -371,7 +405,7 @@ parse_url(const char *url, const char *desc, url_t *type, #ifdef INET6 /* * Check if thost is an encoded IPv6 address, as per - * RFC 2732: + * RFC3986: * `[' ipv6-address ']' */ if (*thost == '[') { @@ -397,8 +431,8 @@ parse_url(const char *url, const char *desc, url_t *type, cp = NULL; } else #endif /* INET6 */ - if ((cp = strchr(thost, ':')) != NULL) - *cp++ = '\0'; + if ((cp = strchr(thost, ':')) != NULL) + *cp++ = '\0'; *host = thost; /* look for [:port] */ @@ -416,17 +450,19 @@ parse_url(const char *url, const char *desc, url_t *type, } if (tport != NULL) - *port = xstrdup(tport); - if (*path == NULL) - *path = xstrdup("/"); - - if (debug) - fprintf(ttyout, - "parse_url: user `%s' pass `%s' host %s port %s(%d) " - "path `%s'\n", - *user ? *user : "<null>", *pass ? *pass : "<null>", - *host ? *host : "<null>", *port ? *port : "<null>", - *portnum ? *portnum : -1, *path ? *path : "<null>"); + *port = ftp_strdup(tport); + if (*path == NULL) { + const char *emptypath = "/"; + if (*type == FTP_URL_T) /* skip first / for ftp URLs */ + emptypath++; + *path = ftp_strdup(emptypath); + } + + DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) " + "path `%s'\n", + *user ? *user : "<null>", *pass ? *pass : "<null>", + *host ? *host : "<null>", *port ? *port : "<null>", + *portnum ? *portnum : -1, *path ? *path : "<null>"); return (0); } @@ -447,21 +483,32 @@ 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 buf[FTPBUFLEN]; + const char *errormsg; + 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; @@ -470,28 +517,12 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) closefunc = NULL; fin = fout = NULL; s = -1; - buf = savefile = NULL; + savefile = NULL; auth = location = message = NULL; ischunked = isproxy = hcode = 0; 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; @@ -513,29 +544,28 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } } - decodedpath = xstrdup(path); + decodedpath = ftp_strdup(path); url_decode(decodedpath); if (outfile) - savefile = xstrdup(outfile); + savefile = ftp_strdup(outfile); else { cp = strrchr(decodedpath, '/'); /* find savefile */ if (cp != NULL) - savefile = xstrdup(cp + 1); + savefile = ftp_strdup(cp + 1); else - savefile = xstrdup(decodedpath); + savefile = ftp_strdup(decodedpath); } if (EMPTYSTRING(savefile)) { if (urltype == FTP_URL_T) { 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 { - if (debug) - fprintf(ttyout, "savefile `%s'\n", savefile); + DPRINTF("savefile `%s'\n", savefile); } restart_point = 0; @@ -551,7 +581,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) { @@ -560,7 +590,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; } @@ -593,13 +623,13 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) /* check URL against list of no_proxied sites */ no_proxy = getoptionvalue("no_proxy"); if (! EMPTYSTRING(no_proxy)) { - char *np, *np_copy; + char *np, *np_copy, *np_iter; long np_port; size_t hlen, plen; - np_copy = xstrdup(no_proxy); + np_iter = np_copy = ftp_strdup(no_proxy); hlen = strlen(host); - while ((cp = strsep(&np_copy, " ,")) != NULL) { + while ((cp = strsep(&np_iter, " ,")) != NULL) { if (*cp == '\0') continue; if ((np = strrchr(cp, ':')) != NULL) { @@ -628,6 +658,11 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } if (isproxy) { + if (restart_point) { + warnx("Can't restart via proxy URL `%s'", + proxyenv); + goto cleanup_fetch_url; + } if (parse_url(proxyenv, "proxy URL", &purltype, &puser, &ppass, &phost, &pport, &portnum, &ppath) == -1) @@ -661,7 +696,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) FREEPTR(port); port = pport; FREEPTR(path); - path = xstrdup(url); + path = ftp_strdup(url); FREEPTR(ppath); } } /* ! EMPTYSTRING(proxyenv) */ @@ -673,7 +708,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) @@ -681,13 +718,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); @@ -698,12 +732,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 (xconnect(s, res->ai_addr, res->ai_addrlen) < 0) { - warn("Connect to address `%s'", hbuf); + if (ftp_connect(s, res->ai_addr, res->ai_addrlen) < 0) { close(s); s = -1; continue; @@ -714,7 +749,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; } @@ -745,7 +780,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) * strip off IPv6 scope identifier, since it is * local to the node */ - h = xstrdup(host); + h = ftp_strdup(host); if (isipv6addr(h) && (p = strchr(h, '%')) != NULL) { *p = '\0'; @@ -804,14 +839,16 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) } /* Read the response */ - if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0)) == NULL) { - warn("Receiving HTTP reply"); + len = getline(fin, buf, sizeof(buf), &errormsg); + if (len < 0) { + if (*errormsg == '\n') + errormsg++; + warnx("Receiving HTTP reply: %s", errormsg); goto cleanup_fetch_url; } while (len > 0 && (ISLWS(buf[len-1]))) buf[--len] = '\0'; - if (debug) - fprintf(ttyout, "received `%s'\n", buf); + DPRINTF("received `%s'\n", buf); /* Determine HTTP response code */ cp = strchr(buf, ' '); @@ -822,22 +859,22 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) hcode = strtol(cp, &ep, 10); if (*ep != '\0' && !isspace((unsigned char)*ep)) goto improper; - message = xstrdup(cp); + message = ftp_strdup(cp); /* Read the rest of the header. */ while (1) { - FREEPTR(buf); - if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0)) - == NULL) { - warn("Receiving HTTP reply"); + len = getline(fin, buf, sizeof(buf), &errormsg); + if (len < 0) { + if (*errormsg == '\n') + errormsg++; + warnx("Receiving HTTP reply: %s", errormsg); goto cleanup_fetch_url; } while (len > 0 && (ISLWS(buf[len-1]))) buf[--len] = '\0'; if (len == 0) break; - if (debug) - fprintf(ttyout, "received `%s'\n", buf); + DPRINTF("received `%s'\n", buf); /* * Look for some headers @@ -849,10 +886,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) filesize = STRTOLL(cp, &ep, 10); if (filesize < 0 || *ep != '\0') goto improper; - if (debug) - fprintf(ttyout, - "parsed len as: " LLF "\n", - (LLT)filesize); + DPRINTF("parsed len as: " LLF "\n", + (LLT)filesize); } else if (match_token(&cp, "Content-Range:")) { if (! match_token(&cp, "bytes")) @@ -884,7 +919,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) if (*cp != '\0') goto improper; - if (debug) { +#ifndef NO_DEBUG + if (ftp_debug) { fprintf(ttyout, "parsed range as: "); if (rangestart == -1) fprintf(ttyout, "*"); @@ -894,6 +930,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) (LLT)rangeend); fprintf(ttyout, "/" LLF "\n", (LLT)entitylen); } +#endif if (! restart_point) { warnx( "Received unexpected Content-Range header"); @@ -904,11 +941,12 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) struct tm parsed; char *t; - /* RFC 1123 */ + memset(&parsed, 0, sizeof(parsed)); + /* RFC1123 */ if ((t = strptime(cp, "%a, %d %b %Y %H:%M:%S GMT", &parsed)) - /* RFC 850 */ + /* RFC0850 */ || (t = strptime(cp, "%a, %d-%b-%y %H:%M:%S GMT", &parsed)) @@ -919,55 +957,49 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) parsed.tm_isdst = -1; if (*t == '\0') mtime = timegm(&parsed); - if (debug && mtime != -1) { +#ifndef NO_DEBUG + if (ftp_debug && mtime != -1) { fprintf(ttyout, "parsed date as: %s", - ctime(&mtime)); + rfc2822time(localtime(&mtime))); } +#endif } } else if (match_token(&cp, "Location:")) { - location = xstrdup(cp); - if (debug) - fprintf(ttyout, - "parsed location as `%s'\n", cp); + location = ftp_strdup(cp); + DPRINTF("parsed location as `%s'\n", cp); } 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; } ischunked++; - if (debug) - fprintf(ttyout, - "using chunked encoding\n"); + DPRINTF("using chunked encoding\n"); } else if (match_token(&cp, "Proxy-Authenticate:") || match_token(&cp, "WWW-Authenticate:")) { if (! (token = match_token(&cp, "Basic"))) { - if (debug) - fprintf(ttyout, + DPRINTF( "skipping unknown auth scheme `%s'\n", token); continue; } FREEPTR(auth); - auth = xstrdup(token); - if (debug) - fprintf(ttyout, - "parsed auth as `%s'\n", cp); + auth = ftp_strdup(token); + DPRINTF("parsed auth as `%s'\n", cp); } } /* finished parsing header */ - FREEPTR(buf); switch (hcode) { case 200: @@ -983,6 +1015,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) case 302: case 303: case 305: + case 307: if (EMPTYSTRING(location)) { warnx( "No redirection Location provided by server"); @@ -1054,7 +1087,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; @@ -1068,7 +1101,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; @@ -1110,7 +1143,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) if (xferbuf) (void)free(xferbuf); bufsize = rcvbuf_size; - xferbuf = xmalloc(bufsize); + xferbuf = ftp_malloc(bufsize); } bytes = 0; @@ -1142,9 +1175,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) warnx("Unexpected data following chunksize"); goto cleanup_fetch_url; } - if (debug) - fprintf(ttyout, "got chunksize of " LLF "\n", - (LLT)chunksize); + DPRINTF("got chunksize of " LLF "\n", (LLT)chunksize); if (chunksize == 0) break; } @@ -1229,7 +1260,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) if (utimes(savefile, tval) == -1) { fprintf(ttyout, "Can't change modification time to %s", - asctime(localtime(&mtime))); + rfc2822time(localtime(&mtime))); } } if (bytes > 0) @@ -1268,7 +1299,6 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) if (ppass != NULL) memset(ppass, 0, strlen(ppass)); FREEPTR(ppass); - FREEPTR(buf); FREEPTR(auth); FREEPTR(location); FREEPTR(message); @@ -1344,18 +1374,18 @@ fetch_ftp(const char *url) } } else { /* classic style `[user@]host:[file]' */ urltype = CLASSIC_URL_T; - host = xstrdup(url); + host = ftp_strdup(url); cp = strchr(host, '@'); if (cp != NULL) { *cp = '\0'; user = host; anonftp = 0; /* disable anonftp */ - host = xstrdup(cp + 1); + host = ftp_strdup(cp + 1); } cp = strchr(host, ':'); if (cp != NULL) { *cp = '\0'; - path = xstrdup(cp + 1); + path = ftp_strdup(cp + 1); } } if (EMPTYSTRING(host)) @@ -1403,14 +1433,12 @@ fetch_ftp(const char *url) url_decode(file); /* but still don't url_decode(dir) */ } - if (debug) - fprintf(ttyout, - "fetch_ftp: user `%s' pass `%s' host %s port %s " - "path `%s' dir `%s' file `%s'\n", - user ? user : "<null>", pass ? pass : "<null>", - host ? host : "<null>", port ? port : "<null>", - path ? path : "<null>", - dir ? dir : "<null>", file ? file : "<null>"); + DPRINTF("fetch_ftp: user `%s' pass `%s' host %s port %s " + "path `%s' dir `%s' file `%s'\n", + user ? user : "<null>", pass ? pass : "<null>", + host ? host : "<null>", port ? port : "<null>", + path ? path : "<null>", + dir ? dir : "<null>", file ? file : "<null>"); dirhasglob = filehasglob = 0; if (doglob && urltype == CLASSIC_URL_T) { @@ -1472,12 +1500,12 @@ fetch_ftp(const char *url) * directories in one step. * * If we are dealing with an `ftp://host/path' URL - * (urltype is FTP_URL_T), then RFC 1738 says we need to + * (urltype is FTP_URL_T), then RFC3986 says we need to * send a separate CWD command for each unescaped "/" * in the path, and we have to interpret %hex escaping * *after* we find the slashes. It's possible to get * empty components here, (from multiple adjacent - * slashes in the path) and RFC 1738 says that we should + * slashes in the path) and RFC3986 says that we should * still do `CWD ' (with a null argument) in such cases. * * Many ftp servers don't support `CWD ', so if there's an @@ -1535,10 +1563,9 @@ fetch_ftp(const char *url) url_decode(dir); } else nextpart = NULL; - if (debug) - fprintf(ttyout, "dir `%s', nextpart `%s'\n", - dir ? dir : "<null>", - nextpart ? nextpart : "<null>"); + DPRINTF("dir `%s', nextpart `%s'\n", + dir ? dir : "<null>", + nextpart ? nextpart : "<null>"); if (urltype == FTP_URL_T || *dir != '\0') { xargv[0] = "cd"; xargv[1] = dir; @@ -1550,8 +1577,8 @@ fetch_ftp(const char *url) fprintf(stderr, "\n" "ftp: The `CWD ' command (without a directory), which is required by\n" -" RFC 1738 to support the empty directory in the URL pathname (`//'),\n" -" conflicts with the server's conformance to RFC 959.\n" +" RFC3986 to support the empty directory in the URL pathname (`//'),\n" +" conflicts with the server's conformance to RFC0959.\n" " Try the same URL without the `//' in the URL pathname.\n" "\n"); goto cleanup_fetch_ftp; @@ -1610,6 +1637,7 @@ fetch_ftp(const char *url) rval = 0; cleanup_fetch_ftp: + FREEPTR(port); FREEPTR(host); FREEPTR(path); FREEPTR(user); @@ -1742,11 +1770,19 @@ auto_fetch(int argc, char *argv[]) } +/* + * Upload multiple files from the command line. + * + * If an error occurs the return value will be the offset+1 in + * argv[] of the file that caused a problem (i.e, argv[x] + * returns x+1) + * Otherwise, 0 is returned if all files uploaded successfully. + */ int auto_put(int argc, char **argv, const char *uploadserver) { char *uargv[4], *path, *pathsep; - int uargc, rval; + int uargc, rval, argpos; size_t len; uargc = 0; @@ -1756,10 +1792,9 @@ auto_put(int argc, char **argv, const char *uploadserver) pathsep = NULL; rval = 1; - if (debug) - fprintf(ttyout, "auto_put: target `%s'\n", uploadserver); + DPRINTF("auto_put: target `%s'\n", uploadserver); - path = xstrdup(uploadserver); + path = ftp_strdup(uploadserver); len = strlen(path); if (path[len - 1] != '/' && path[len - 1] != ':') { /* @@ -1768,7 +1803,7 @@ auto_put(int argc, char **argv, const char *uploadserver) if (argc > 1) { /* more than one file to upload */ len = strlen(uploadserver) + 2; /* path + "/" + "\0" */ free(path); - path = (char *)xmalloc(len); + path = (char *)ftp_malloc(len); (void)strlcpy(path, uploadserver, len); (void)strlcat(path, "/", len); } else { /* single file to upload */ @@ -1781,38 +1816,44 @@ auto_put(int argc, char **argv, const char *uploadserver) goto cleanup_auto_put; } pathsep++; - uargv[2] = xstrdup(pathsep); + uargv[2] = ftp_strdup(pathsep); pathsep[0] = '/'; } else - uargv[2] = xstrdup(pathsep + 1); + uargv[2] = ftp_strdup(pathsep + 1); pathsep[1] = '\0'; uargc++; } } - if (debug) - fprintf(ttyout, "auto_put: URL `%s' argv[2] `%s'\n", - path, uargv[2] ? uargv[2] : "<null>"); + DPRINTF("auto_put: URL `%s' argv[2] `%s'\n", + path, uargv[2] ? uargv[2] : "<null>"); /* connect and cwd */ rval = auto_fetch(1, &path); - free(path); if(rval >= 0) goto cleanup_auto_put; + rval = 0; + + /* target filename provided; upload 1 file */ /* XXX : is this the best way? */ if (uargc == 3) { uargv[1] = argv[0]; put(uargc, uargv); - goto cleanup_auto_put; - } - - for(; argv[0] != NULL; argv++) { - uargv[1] = argv[0]; - mput(uargc, uargv); + if ((code / 100) != COMPLETE) + rval = 1; + } else { /* otherwise a target dir: upload all files to it */ + for(argpos = 0; argv[argpos] != NULL; argpos++) { + uargv[1] = argv[argpos]; + mput(uargc, uargv); + if ((code / 100) != COMPLETE) { + rval = argpos + 1; + break; + } + } } - rval = 0; cleanup_auto_put: + free(path); FREEPTR(uargv[2]); return (rval); } diff --git a/net/tnftp/files/src/ftp.1 b/net/tnftp/files/src/ftp.1 index eda2f1d7015..5737a3defec 100644 --- a/net/tnftp/files/src/ftp.1 +++ b/net/tnftp/files/src/ftp.1 @@ -1,7 +1,7 @@ -.\" NetBSD: ftp.1,v 1.7 2005/05/11 02:41:28 lukem Exp -.\" from NetBSD: ftp.1,v 1.109 2005/02/20 20:54:01 wiz Exp +.\" $NetBSD: ftp.1,v 1.1.1.4 2007/08/06 04:33:23 lukem Exp $ +.\" from NetBSD: ftp.1,v 1.119 2007/07/18 06:40:01 lukem Exp .\" -.\" Copyright (c) 1996-2004 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 @@ -65,7 +65,7 @@ .\" .\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 .\" -.Dd January 15, 2005 +.Dd July 18, 2007 .Dt FTP 1 .Os .Sh NAME @@ -87,6 +87,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 @@ -180,7 +181,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 @@ -273,16 +274,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,8 +357,8 @@ is awaiting commands from the user the prompt is provided to the user. The following commands are recognized by -.Nm ftp : -.Bl -tag -width Fl +.Nm ftp : +.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 @@ -456,10 +461,10 @@ when an ascii type transfer is made, these linefeeds may be distinguished from a record delimiter only when .Ic \&cr is off. -.It Ic debug Op Ar debug-value +.It Ic ftp_debug Op Ar ftp_debug-value Toggle debugging mode. If an optional -.Ar debug-value +.Ar ftp_debug-value is specified it is used to set the debugging level. When debugging is on, .Nm @@ -614,8 +619,9 @@ transferring a .Xr tar 1 archive of the subtree (in binary mode). .It Ic hash Op Ar size -Toggle hash-sign (``#'') printing for each data block -transferred. +Toggle hash-sign +.Pq Sq # +printing for each data block transferred. The size of a data block defaults to 1024 bytes. This can be changed by specifying .Ar size @@ -664,24 +670,49 @@ A synonym for Define a macro. Subsequent lines are stored as the macro .Ar macro-name ; -a null line (consecutive newline characters -in a file or -carriage returns from the terminal) terminates macro input mode. +a null line (consecutive newline characters in a file or carriage +returns from the terminal) terminates macro input mode. There is a limit of 16 macros and 4096 total characters in all defined macros. -Macros remain defined until a +Macro names can be a maximum of 8 characters. +Macros are only applicable to the current session they are +defined within (or if defined outside a session, to the session +invoked with the next +.Ic open +command), and remain defined until a .Ic close command is executed. -The macro processor interprets `$' and `\e' as special characters. -A `$' followed by a number (or numbers) is replaced by the +To invoke a macro, use the +.Ic $ +command (see above). +.Pp +The macro processor interprets +.Sq $ +and +.Sq \e +as special characters. +A +.Sq $ +followed by a number (or numbers) is replaced by the corresponding argument on the macro invocation command line. -A `$' followed by an `i' signals that macro processor that the -executing macro is to be looped. -On the first pass `$i' is -replaced by the first argument on the macro invocation command line, -on the second pass it is replaced by the second argument, and so on. -A `\e' followed by any character is replaced by that character. -Use the `\e' to prevent special treatment of the `$'. +A +.Sq $ +followed by an +.Sq i +signals the macro processor that the executing macro is to be +looped. +On the first pass +.Dq $i +is replaced by the first argument on the macro invocation command +line, on the second pass it is replaced by the second argument, +and so on. +A +.Sq \e +followed by any character is replaced by that character. +Use the +.Sq \e +to prevent special treatment of the +.Sq $ . .It Ic mdelete Op Ar remote-files Delete the .Ar remote-files @@ -757,7 +788,9 @@ The default (and only supported) mode is .Dq stream . .It Ic modtime Ar remote-file -Show the last modification time of the file on the remote machine. +Show the last modification time of the file on the remote machine, in +.Li RFC2822 +format. .It Ic more Ar file A synonym for .Ic page . @@ -824,9 +857,18 @@ and .Ic case settings). Variable templating is accomplished by including the -sequences `$1', `$2', ..., `$9' in +sequences +.Dq $1 , +.Dq $2 , +\&... +.Dq $9 +in .Ar inpattern . -Use `\\' to prevent this special treatment of the `$' character. +Use +.Sq \e +to prevent this special treatment of the +.Sq $ +character. All other characters are treated literally, and are used to determine the .Ic nmap .Op Ar inpattern @@ -838,13 +880,19 @@ $1.$2 and the remote file name "mydata.data", $1 would have the value The .Ar outpattern determines the resulting mapped filename. -The sequences `$1', `$2', ...., `$9' are replaced by any value resulting -from the +The sequences +.Dq $1 , +.Dq $2 , +\&... +.Dq $9 +are replaced by any value resulting from the .Ar inpattern template. -The sequence `$0' is replace by the original filename. +The sequence +.Dq $0 +is replaced by the original filename. Additionally, the sequence -.Ql Op Ar seq1 , Ar seq2 +.Dq Op Ar seq1 , Ar seq2 is replaced by .Op Ar seq1 if @@ -863,9 +911,18 @@ the output filename "myfile.data" for input filenames "myfile.data" and "myfile.myfile" for the input filename ".myfile". Spaces may be included in .Ar outpattern , -as in the example: `nmap $1 sed "s/ *$//" \*[Gt] $1' . -Use the `\e' character to prevent special treatment -of the `$','[',']', and `,' characters. +as in the example: +.Dl nmap $1 sed "s/ *$//" \*[Gt] $1 +Use the +.Sq \e +character to prevent special treatment +of the +.Sq $ , +.Sq \&[ , +.Sq \&] , +and +.Sq \&, +characters. .It Ic ntrans Op Ar inchars Op Ar outchars Set or unset the filename character translation mechanism. If no arguments are specified, the filename character @@ -953,7 +1010,7 @@ traffic. servers are required to support the .Dv PASV command by -.Li RFC 1123 , +.Li RFC1123 , some do not.) .It Ic pdir Op Ar remote-path Perform @@ -1440,7 +1497,9 @@ A synonym for .El .Pp Command arguments which have embedded spaces may be quoted with -quote `"' marks. +quote +.Sq \&" +marks. .Pp Commands which toggle settings can take an explicit .Ic on @@ -1566,7 +1625,7 @@ ascii or binary (respectively). The default transfer type is binary. .Pp In order to be compliant with -.Li RFC 1738 , +.Li RFC3986 , .Nm interprets the .Ar path @@ -1619,7 +1678,7 @@ Any .Sq Li \&% Ns Ar XX codes (per -.Li RFC 1738 ) +.Li RFC3986 ) within the path components are decoded, with .Ar XX representing a character code in hexadecimal. @@ -1744,6 +1803,26 @@ is in the URL, use them for the first attempt to authenticate. A local URL, copied from .Pa / Ns Ar path on the local host. +.\" about: +.It Xo +.Sm off +.Li about: +.Ar topic +.Sm on +.Xc +Display information regarding +.Ar topic ; +no file is retrieved for this auto-fetched element. +Supported values include: +.Bl -tag -width "about:version" +.It Li about:ftp +Information about +.Nm ftp . +.It Li about:version +The version of +.Nm ftp . +Useful to provide when reporting problems. +.El .El .Pp Unless noted otherwise above, and @@ -1869,11 +1948,12 @@ A particularly useful example of this mechanism is: .Dq Li dir \&"\&" \&|more . .It -Failing the above checks, if ``globbing'' is enabled, -local file names are expanded -according to the rules used in the +Failing the above checks, if +.Dq globbing +is enabled, local file names are expanded according to the rules +used in the .Xr csh 1 ; -c.f. the +see the .Ic glob command. If the @@ -2039,6 +2119,20 @@ next .Pa .netrc line and continue until a blank line (consecutive new-line characters) is encountered. +Like the other tokens in the +.Pa .netrc +file, a +.Ic macdef +is applicable only to the +.Ic machine +definition preceding it. +A +.Ic macdef +entry cannot be utilized by multiple +.Ic machine +definitions; rather, it must be defined following each +.Ic machine +it is intended to be used with. If a macro named .Ic init is defined, it is automatically executed as the last step in the @@ -2249,7 +2343,7 @@ URL characters are required in the username or password or .Sq / ) , encode them with -.Li RFC 1738 +.Li RFC3986 .Sq Li \&% Ns Ar XX encoding. .Pp @@ -2292,16 +2386,27 @@ for an example of how to make this automatic. .Xr ftpd 8 .Sh STANDARDS .Nm -attempts to be compliant with -.Li RFC 959 , -.Li RFC 1123 , -.Li RFC 1738 , -.Li RFC 2068 , -.Li RFC 2389 , -.Li RFC 2428 , -.Li RFC 2732 , -and -.Cm draft-ietf-ftpext-mlst-11 . +attempts to be compliant with: +.Bl -tag -offset indent -width 8n +.It Li RFC0959 +.Em File Transfer Protocol +.It Li RFC1123 +.Em Requirements for Internet Hosts - Application and Support +.It Li RFC1635 +.Em How to Use Anonymous FTP +.It Li RFC2389 +.Em Feature negotiation mechanism for the File Transfer Protocol +.It Li RFC2428 +.Em FTP Extensions for IPv6 and NATs +.It Li RFC2616 +.Em Hypertext Transfer Protocol -- HTTP/1.1 +.It Li RFC2822 +.Em Internet Message Format +.It Li RFC3659 +.Em Extensions to FTP +.It Li RFC3986 +.Em Uniform Resource Identifier (URI) +.El .Sh HISTORY The .Nm diff --git a/net/tnftp/files/src/ftp.c b/net/tnftp/files/src/ftp.c index 770685370a7..a94006b9ba1 100644 --- a/net/tnftp/files/src/ftp.c +++ b/net/tnftp/files/src/ftp.c @@ -1,8 +1,8 @@ -/* NetBSD: ftp.c,v 1.11 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: ftp.c,v 1.134 2005/06/10 00:18:46 lukem Exp */ +/* $NetBSD: ftp.c,v 1.1.1.6 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: ftp.c,v 1.152 2007/07/22 05:02:50 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 @@ -96,9 +96,45 @@ */ #include "tnftp.h" +#include <arpa/telnet.h> + +#if 0 /* tnftp */ +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; +#else +__RCSID(" NetBSD: ftp.c,v 1.152 2007/07/22 05:02:50 lukem Exp "); +#endif +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <arpa/inet.h> +#include <arpa/ftp.h> #include <arpa/telnet.h> +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <stdarg.h> + +#endif /* tnftp */ + #include "ftp_var.h" volatile sig_atomic_t abrtflag; @@ -118,12 +154,12 @@ struct sockinet { struct sockaddr_in6 su_sin6; #endif } si_su; -#if !HAVE_SOCKADDR_SA_LEN +#if !defined(HAVE_STRUCT_SOCKADDR_SA_LEN) int si_len; #endif }; -#if !HAVE_SOCKADDR_SA_LEN +#if !defined(HAVE_STRUCT_SOCKADDR_SA_LEN) # define su_len si_len #else # define su_len si_su.su_sin.sin_len @@ -140,7 +176,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; @@ -154,7 +189,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); } @@ -167,49 +204,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 = xconnect(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; @@ -219,7 +229,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; @@ -231,7 +241,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; } @@ -242,8 +252,7 @@ hookup(char *host, char *port) int tos = IPTOS_LOWDELAY; if (setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(tos)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", + DWARN("setsockopt %s (ignored)", "IPTOS_LOWDELAY"); } } @@ -251,7 +260,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) @@ -272,8 +281,7 @@ hookup(char *host, char *port) if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *)&on, sizeof(on)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", "SO_OOBINLINE"); + DWARN("setsockopt %s (ignored)", "SO_OOBINLINE"); } return (hostname); @@ -319,7 +327,8 @@ command(const char *fmt, ...) int r; sigfunc oldsigint; - if (debug) { +#ifndef NO_DEBUG + if (ftp_debug) { fputs("---> ", ttyout); va_start(ap, fmt); if (strncmp("PASS ", fmt, 5) == 0) @@ -331,8 +340,9 @@ command(const char *fmt, ...) va_end(ap); putc('\n', ttyout); } +#endif if (cout == NULL) { - warnx("No control connection for command."); + warnx("No control connection for command"); code = -1; return (0); } @@ -354,6 +364,12 @@ command(const char *fmt, ...) return (r); } +static const char *m421[] = { + "remote server timed out. Connection closed", + "user interrupt. Connection closed", + "remote server has closed connection", +}; + int getreply(int expecteof) { @@ -374,7 +390,8 @@ getreply(int expecteof) for (line = 0 ;; line++) { dig = n = code = 0; cp = current_line; - while (alarmtimer(60),((c = getc(cin)) != '\n')) { + while (alarmtimer(quit_time ? quit_time : 60), + ((c = getc(cin)) != '\n')) { if (c == IAC) { /* handle telnet commands */ switch (c = getc(cin)) { case WILL: @@ -413,18 +430,15 @@ getreply(int expecteof) cpend = 0; lostpeer(0); if (verbose) { + size_t midx; if (reply_timeoutflag) - fputs( - "421 Service not available, remote server timed out. Connection closed\n", - ttyout); + midx = 0; else if (reply_abrtflag) - fputs( - "421 Service not available, user interrupt. Connection closed.\n", - ttyout); + midx = 1; else - fputs( - "421 Service not available, remote server has closed connection.\n", - ttyout); + midx = 2; + (void)fprintf(ttyout, + "421 Service not available, %s.\n", m421[midx]); (void)fflush(ttyout); } code = 421; @@ -473,7 +487,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'; @@ -521,7 +535,7 @@ empty(FILE *cin, FILE *din, int sec) pfd[nfd++].events = POLLIN; } - if ((nr = xpoll(pfd, nfd, sec * 1000)) <= 0) + if ((nr = ftp_poll(pfd, nfd, sec * 1000)) <= 0) return nr; nr = 0; @@ -553,8 +567,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)); @@ -562,30 +575,108 @@ abortxfer(int notused) siglongjmp(xferabort, 1); } +/* + * Read data from infd & write to outfd, using buf/bufsize as the temporary + * buffer, dealing with short writes. + * If rate_limit != 0, rate-limit the transfer. + * If hash_interval != 0, fputc('c', ttyout) every hash_interval bytes. + * Updates global variables: bytes. + * Returns 0 if ok, 1 if there was a read error, 2 if there was a write error. + * In the case of error, errno contains the appropriate error code. + */ +static int +copy_bytes(int infd, int outfd, char *buf, size_t bufsize, + int rate_limit, int hash_interval) +{ + volatile off_t hashc; + ssize_t inc, outc; + char *bufp; + struct timeval tvthen, tvnow, tvdiff; + off_t bufrem, bufchunk; + int serr; + + hashc = hash_interval; + if (rate_limit) + bufchunk = rate_limit; + else + bufchunk = bufsize; + + while (1) { + if (rate_limit) { + (void)gettimeofday(&tvthen, NULL); + } + errno = 0; + inc = outc = 0; + /* copy bufchunk at a time */ + bufrem = bufchunk; + while (bufrem > 0) { + inc = read(infd, buf, MIN(bufsize, bufrem)); + if (inc <= 0) + goto copy_done; + bytes += inc; + bufrem -= inc; + bufp = buf; + while (inc > 0) { + outc = write(outfd, bufp, inc); + if (outc < 0) + goto copy_done; + inc -= outc; + bufp += outc; + } + if (hash_interval) { + while (bytes >= hashc) { + (void)putc('#', ttyout); + hashc += hash_interval; + } + (void)fflush(ttyout); + } + } + if (rate_limit) { /* rate limited; wait if necessary */ + while (1) { + (void)gettimeofday(&tvnow, NULL); + timersub(&tvnow, &tvthen, &tvdiff); + if (tvdiff.tv_sec > 0) + break; + usleep(1000000 - tvdiff.tv_usec); + } + } + } + + copy_done: + serr = errno; + if (hash_interval && bytes > 0) { + if (bytes < hash_interval) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + (void)fflush(ttyout); + } + errno = serr; + if (inc == -1) + return 1; + if (outc == -1) + return 2; + + return 0; +} + void sendrequest(const char *cmd, const char *local, const char *remote, int printnames) { struct stat st; - int c, d; - FILE *fin, *dout; - int (*closefunc)(FILE *); - sigfunc oldintr, oldintp; - volatile off_t hashbytes; - char *lmode, *bufp; + int c; + FILE *volatile fin; + FILE *volatile dout; + int (*volatile closefunc)(FILE *); + sigfunc volatile oldintr; + sigfunc volatile oldintp; + off_t volatile hashbytes; + int hash_interval; + char *volatile lmode; 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; -#endif - hashbytes = mark; direction = "sent"; dout = NULL; @@ -593,7 +684,7 @@ sendrequest(const char *cmd, const char *local, const char *remote, filesize = -1; oprogress = progress; if (verbose && printnames) { - if (local && *local != '-') + if (*local != '-') fprintf(ttyout, "local: %s ", local); if (remote) fprintf(ttyout, "remote: %s\n", remote); @@ -623,7 +714,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; } @@ -632,7 +723,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; } @@ -666,7 +757,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) @@ -689,86 +780,24 @@ sendrequest(const char *cmd, const char *local, const char *remote, if (buf) (void)free(buf); bufsize = sndbuf_size; - buf = xmalloc(bufsize); + buf = ftp_malloc(bufsize); } progressmeter(-1); oldintp = xsignal(SIGPIPE, SIG_IGN); + hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0; switch (curtype) { case TYPE_I: case TYPE_L: - if (rate_put) { /* rate limited */ - while (1) { - struct timeval then, now, td; - off_t bufrem; - - (void)gettimeofday(&then, NULL); - errno = c = d = 0; - bufrem = rate_put; - while (bufrem > 0) { - if ((c = read(fileno(fin), buf, - MIN(bufsize, bufrem))) <= 0) - goto senddone; - bytes += c; - bufrem -= c; - for (bufp = buf; c > 0; - c -= d, bufp += d) - if ((d = write(fileno(dout), - bufp, c)) <= 0) - break; - if (d < 0) - goto senddone; - if (hash && - (!progress || filesize < 0) ) { - while (bytes >= hashbytes) { - (void)putc('#', ttyout); - hashbytes += mark; - } - (void)fflush(ttyout); - } - } - while (1) { - (void)gettimeofday(&now, NULL); - timersub(&now, &then, &td); - if (td.tv_sec > 0) - break; - usleep(1000000 - td.tv_usec); - } - } - } else { /* simpler/faster; no rate limit */ - while (1) { - errno = c = d = 0; - if ((c = read(fileno(fin), buf, bufsize)) <= 0) - goto senddone; - bytes += c; - for (bufp = buf; c > 0; c -= d, bufp += d) - if ((d = write(fileno(dout), bufp, c)) - <= 0) - break; - if (d < 0) - goto senddone; - if (hash && (!progress || filesize < 0) ) { - while (bytes >= hashbytes) { - (void)putc('#', ttyout); - hashbytes += mark; - } - (void)fflush(ttyout); - } - } - } - senddone: - if (hash && (!progress || filesize < 0) && bytes > 0) { - if (bytes < mark) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - } - if (c < 0) - warn("local: %s", local); - if (d < 0) { + c = copy_bytes(fileno(fin), fileno(dout), buf, bufsize, + rate_put, hash_interval); + if (c == 1) { + warn("Reading `%s'", local); + } else if (c == 2) { if (errno != EPIPE) - warn("netout"); + warn("Writing to network"); bytes = -1; } break; @@ -776,8 +805,7 @@ sendrequest(const char *cmd, const char *local, const char *remote, case TYPE_A: while ((c = getc(fin)) != EOF) { if (c == '\n') { - while (hash && (!progress || filesize < 0) && - (bytes >= hashbytes)) { + while (hash_interval && bytes >= hashbytes) { (void)putc('#', ttyout); (void)fflush(ttyout); hashbytes += mark; @@ -789,23 +817,23 @@ sendrequest(const char *cmd, const char *local, const char *remote, } (void)putc(c, dout); bytes++; -#if 0 /* this violates RFC */ +#if 0 /* this violates RFC0959 */ if (c == '\r') { (void)putc('\0', dout); bytes++; } #endif } - if (hash && (!progress || filesize < 0)) { + if (hash_interval) { if (bytes < hashbytes) (void)putc('#', ttyout); (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; @@ -862,32 +890,28 @@ 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; + int hash_interval; 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; @@ -899,7 +923,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, opreserve = preserve; is_retr = (strcmp(cmd, "RETR") == 0); if (is_retr && verbose && printnames) { - if (local && (ignorespecial || *local != '-')) + if (ignorespecial || *local != '-') fprintf(ttyout, "local: %s ", local); if (remote) fprintf(ttyout, "remote: %s\n", remote); @@ -925,7 +949,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; } @@ -936,13 +960,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; } @@ -994,7 +1018,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; @@ -1003,7 +1027,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; @@ -1017,10 +1041,11 @@ recvrequest(const char *cmd, const char *local, const char *remote, if (buf) (void)free(buf); bufsize = rcvbuf_size; - buf = xmalloc(bufsize); + buf = ftp_malloc(bufsize); } progressmeter(-1); + hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0; switch (curtype) { @@ -1028,76 +1053,17 @@ 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 */ - while (1) { - struct timeval then, now, td; - off_t bufrem; - - (void)gettimeofday(&then, NULL); - errno = c = d = 0; - for (bufrem = rate_get; bufrem > 0; ) { - if ((c = read(fileno(din), buf, - MIN(bufsize, bufrem))) <= 0) - goto recvdone; - bytes += c; - bufrem -=c; - if ((d = write(fileno(fout), buf, c)) - != c) - goto recvdone; - if (hash && - (!progress || filesize < 0)) { - while (bytes >= hashbytes) { - (void)putc('#', ttyout); - hashbytes += mark; - } - (void)fflush(ttyout); - } - } - /* sleep until time is up */ - while (1) { - (void)gettimeofday(&now, NULL); - timersub(&now, &then, &td); - if (td.tv_sec > 0) - break; - usleep(1000000 - td.tv_usec); - } - } - } else { /* faster code (no limiting) */ - while (1) { - errno = c = d = 0; - if ((c = read(fileno(din), buf, bufsize)) <= 0) - goto recvdone; - bytes += c; - if ((d = write(fileno(fout), buf, c)) != c) - goto recvdone; - if (hash && (!progress || filesize < 0)) { - while (bytes >= hashbytes) { - (void)putc('#', ttyout); - hashbytes += mark; - } - (void)fflush(ttyout); - } - } - } - recvdone: - if (hash && (!progress || filesize < 0) && bytes > 0) { - if (bytes < mark) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - } - if (c < 0) { + c = copy_bytes(fileno(din), fileno(fout), buf, bufsize, + rate_get, hash_interval); + if (c == 1) { if (errno != EPIPE) - warn("netin"); + warn("Reading from network"); bytes = -1; - } - if (d < c) { - if (d < 0) - warn("local: %s", local); - else - warnx("%s: short write", local); + } else if (c == 2) { + warn("Writing `%s'", local); } break; @@ -1116,7 +1082,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; } } @@ -1124,8 +1090,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, if (c == '\n') bare_lfs++; while (c == '\r') { - while (hash && (!progress || filesize < 0) && - (bytes >= hashbytes)) { + while (hash_interval && bytes >= hashbytes) { (void)putc('#', ttyout); (void)fflush(ttyout); hashbytes += mark; @@ -1148,18 +1113,18 @@ recvrequest(const char *cmd, const char *local, const char *remote, contin2: ; } break2: - if (hash && (!progress || filesize < 0)) { + if (hash_interval) { if (bytes < hashbytes) (void)putc('#', ttyout); (void)putc('\n', ttyout); } 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; } @@ -1189,7 +1154,8 @@ recvrequest(const char *cmd, const char *local, const char *remote, if (utimes(local, tval) == -1) { fprintf(ttyout, "Can't change modification time on %s to %s", - local, asctime(localtime(&mtime))); + local, + rfc2822time(localtime(&mtime))); } } } @@ -1198,7 +1164,7 @@ recvrequest(const char *cmd, const char *local, const char *remote, abort: /* - * abort using RFC 959 recommended IP,SYNC sequence + * abort using RFC0959 recommended IP,SYNC sequence */ if (! sigsetjmp(xferabort, 1)) { /* this is the first call */ @@ -1246,34 +1212,44 @@ initconn(void) unsigned int af, hal, pal; socklen_t len; char *pasvcmd = NULL; + int overbose; #ifdef INET6 - if (myctladdr.su_family == AF_INET6 && debug && +#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) && setsockopt(data, SOL_SOCKET, SO_DEBUG, (void *)&on, sizeof(on)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", "SO_DEBUG"); + DWARN("setsockopt %s (ignored)", "SO_DEBUG"); } result = COMPLETE + 1; switch (data_addr.su_family) { 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); /* @@ -1288,10 +1264,8 @@ initconn(void) } if (result != COMPLETE) { epsv4bad = 1; - if (debug) - fputs( - "disabling epsv4 for this connection\n", - ttyout); + DPRINTF("disabling epsv4 for this " + "connection\n"); } } if (result != COMPLETE) { @@ -1304,7 +1278,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 */ @@ -1484,8 +1465,8 @@ initconn(void) } else goto bad; - while (xconnect(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; @@ -1495,7 +1476,6 @@ initconn(void) #endif goto reinit; } - warn("connect for data channel"); goto bad; } #ifdef IPTOS_THROUGHPUT @@ -1503,9 +1483,8 @@ initconn(void) on = IPTOS_THROUGHPUT; if (setsockopt(data, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(on)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", - "IPTOS_THROUGHPUT"); + DWARN("setsockopt %s (ignored)", + "IPTOS_THROUGHPUT"); } } #endif @@ -1520,7 +1499,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); @@ -1528,29 +1507,28 @@ 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) && setsockopt(data, SOL_SOCKET, SO_DEBUG, (void *)&on, sizeof(on)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", "SO_DEBUG"); + DWARN("setsockopt %s (ignored)", "SO_DEBUG"); } 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 (xlisten(data, 1) < 0) - warn("listen"); + if (ftp_listen(data, 1) < 0) + warn("Can't listen to data connection"); if (sendport) { char hname[NI_MAXHOST], sname[NI_MAXSERV]; @@ -1578,16 +1556,21 @@ 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) { epsv4bad = 1; - if (debug) - fputs( - "disabling epsv4 for this connection\n", - ttyout); + DPRINTF("disabling epsv4 for this " + "connection\n"); } } break; @@ -1641,9 +1624,7 @@ initconn(void) on = IPTOS_THROUGHPUT; if (setsockopt(data, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(on)) == -1) - if (debug) - warn("setsockopt %s (ignored)", - "IPTOS_THROUGHPUT"); + DWARN("setsockopt %s (ignored)", "IPTOS_THROUGHPUT"); } #endif return (0); @@ -1688,14 +1669,14 @@ dataconn(const char *lmode) timeout = td.tv_sec * 1000 + td.tv_usec/1000; if (timeout < 0) timeout = 0; - rv = xpoll(pfd, 1, timeout); + 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; } @@ -1705,7 +1686,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; } @@ -1719,9 +1700,7 @@ dataconn(const char *lmode) int tos = IPTOS_THROUGHPUT; if (setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(tos)) == -1) { - if (debug) - warn("setsockopt %s (ignored)", - "IPTOS_THROUGHPUT"); + DWARN("setsockopt %s (ignored)", "IPTOS_THROUGHPUT"); } } #endif @@ -1848,15 +1827,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; @@ -1960,7 +1934,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); @@ -1982,13 +1956,13 @@ reset(int argc, char *argv[]) int nfnd = 1; if (argc == 0 && argv != NULL) { - fprintf(ttyout, "usage: %s\n", argv[0]); + UPRINTF("usage: %s\n", argv[0]); code = -1; return; } while (nfnd > 0) { if ((nfnd = empty(cin, NULL, 0)) < 0) { - warn("reset"); + warn("Error resetting connection"); code = -1; lostpeer(0); } else if (nfnd) @@ -2010,7 +1984,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)); @@ -2070,7 +2044,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); @@ -2084,12 +2058,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); @@ -2105,6 +2079,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) { @@ -2130,10 +2122,18 @@ ai_unmapped(struct addrinfo *ai) sin.sin_port = sin6->sin6_port; ai->ai_family = AF_INET; -#if HAVE_SOCKADDR_SA_LEN +#if defined(HAVE_STRUCT_SOCKADDR_SA_LEN) sin.sin_len = len; #endif memcpy(ai->ai_addr, &sin, len); ai->ai_addrlen = len; #endif } + +#ifdef NO_USAGE +void +xusage(void) +{ + fputs("Usage error\n", ttyout); +} +#endif diff --git a/net/tnftp/files/src/ftp.cat1 b/net/tnftp/files/src/ftp.cat1 index ae1d6fb32df..4ce9af518a0 100644 --- a/net/tnftp/files/src/ftp.cat1 +++ b/net/tnftp/files/src/ftp.cat1 @@ -5,7 +5,7 @@ NNAAMMEE SSYYNNOOPPSSIISS ffttpp [--4466AAaaddeeffggiinnppRRttvvVV] [--NN _n_e_t_r_c] [--oo _o_u_t_p_u_t] [--PP _p_o_r_t] [--qq _q_u_i_t_t_i_m_e] - [--rr _r_e_t_r_y] [--TT _d_i_r,_m_a_x[,_i_n_c]] [[_u_s_e_r@]_h_o_s_t [_p_o_r_t]] + [--ss _s_r_c_a_d_d_r] [--rr _r_e_t_r_y] [--TT _d_i_r,_m_a_x[,_i_n_c]] [[_u_s_e_r@]_h_o_s_t [_p_o_r_t]] [[_u_s_e_r@]_h_o_s_t:[_p_a_t_h][/]] [file:///_p_a_t_h] [ftp://[_u_s_e_r[:_p_a_s_s_w_o_r_d]@]_h_o_s_t[:_p_o_r_t]/_p_a_t_h[/][;type=_X]] [http://[_u_s_e_r[:_p_a_s_s_w_o_r_d]@]_h_o_s_t[:_p_o_r_t]/_p_a_t_h] [_._._.] @@ -23,88 +23,92 @@ DDEESSCCRRIIPPTTIIOONN Options may be specified at the command line, or to the command inter- preter. - --44 Forces ffttpp to only use IPv4 addresses. + --44 Forces ffttpp to only use IPv4 addresses. - --66 Forces ffttpp to only use IPv6 addresses. + --66 Forces ffttpp to only use IPv6 addresses. - --AA Force active mode ftp. By default, ffttpp will try to use passive - mode ftp and fall back to active mode if passive is not sup- - ported by the server. This option causes ffttpp to always use an - active connection. It is only useful for connecting to very old - servers that do not implement passive mode properly. + --AA Force active mode ftp. By default, ffttpp will try to use pas- + sive mode ftp and fall back to active mode if passive is not + supported by the server. This option causes ffttpp to always + use an active connection. It is only useful for connecting + to very old servers that do not implement passive mode prop- + erly. - --aa Causes ffttpp to bypass normal login procedure, and use an anony- - mous login instead. + --aa Causes ffttpp to bypass normal login procedure, and use an + anonymous login instead. - --dd Enables debugging. + --dd Enables debugging. - --ee Disables command line editing. This is useful for Emacs ange- - ftp mode. + --ee Disables command line editing. This is useful for Emacs + ange-ftp mode. - --ff Forces a cache reload for transfers that go through the FTP or - HTTP proxies. + --ff Forces a cache reload for transfers that go through the FTP + or HTTP proxies. - --gg Disables file name globbing. + --gg Disables file name globbing. - --ii Turns off interactive prompting during multiple file transfers. + --ii Turns off interactive prompting during multiple file trans- + fers. - --nn Restrains ffttpp from attempting ``auto-login'' upon initial con- - nection for non auto-fetch transfers. If auto-login is enabled, - ffttpp will check the _._n_e_t_r_c (see below) file in the user's home - directory for an entry describing an account on the remote - machine. If no entry exists, ffttpp will prompt for the remote - machine login name (default is the user identity on the local - machine), and, if necessary, prompt for a password and an - account with which to login. To override the auto-login for - auto-fetch transfers, specify the username (and optionally, - password) as appropriate. + --nn Restrains ffttpp from attempting ``auto-login'' upon initial + connection for non auto-fetch transfers. If auto-login is + enabled, ffttpp will check the _._n_e_t_r_c (see below) file in the + user's home directory for an entry describing an account on + the remote machine. If no entry exists, ffttpp will prompt for + the remote machine login name (default is the user identity + on the local machine), and, if necessary, prompt for a pass- + word and an account with which to login. To override the + auto-login for auto-fetch transfers, specify the username + (and optionally, password) as appropriate. - --NN _n_e_t_r_c - Use _n_e_t_r_c instead of _~_/_._n_e_t_r_c. Refer to _T_H_E _._n_e_t_r_c _F_I_L_E for - more information. + --NN _n_e_t_r_c Use _n_e_t_r_c instead of _~_/_._n_e_t_r_c. Refer to _T_H_E _._n_e_t_r_c _F_I_L_E for + more information. - --oo _o_u_t_p_u_t - When auto-fetching files, save the contents in _o_u_t_p_u_t. _o_u_t_p_u_t - is parsed according to the _F_I_L_E _N_A_M_I_N_G _C_O_N_V_E_N_T_I_O_N_S below. If - _o_u_t_p_u_t is not `-' or doesn't start with `|', then only the first - file specified will be retrieved into _o_u_t_p_u_t; all other files - will be retrieved into the basename of their remote name. + --oo _o_u_t_p_u_t When auto-fetching files, save the contents in _o_u_t_p_u_t. + _o_u_t_p_u_t is parsed according to the _F_I_L_E _N_A_M_I_N_G _C_O_N_V_E_N_T_I_O_N_S + below. If _o_u_t_p_u_t is not `-' or doesn't start with `|', then + only the first file specified will be retrieved into _o_u_t_p_u_t; + all other files will be retrieved into the basename of their + remote name. - --pp Enable passive mode operation for use behind connection filter- - ing firewalls. This option has been deprecated as ffttpp now tries - to use passive mode by default, falling back to active mode if - the server does not support passive connections. + --pp Enable passive mode operation for use behind connection fil- + tering firewalls. This option has been deprecated as ffttpp now + tries to use passive mode by default, falling back to active + mode if the server does not support passive connections. - --PP _p_o_r_t Sets the port number to _p_o_r_t. - - --rr _w_a_i_t Retry the connection attempt if it failed, pausing for _w_a_i_t sec- - onds. + --PP _p_o_r_t Sets the port number to _p_o_r_t. --qq _q_u_i_t_t_i_m_e - Quit if the connection has stalled for _q_u_i_t_t_i_m_e seconds. + Quit if the connection has stalled for _q_u_i_t_t_i_m_e seconds. + + --rr _w_a_i_t Retry the connection attempt if it failed, pausing for _w_a_i_t + seconds. - --RR Restart all non-proxied auto-fetches. + --RR Restart all non-proxied auto-fetches. - --tt Enables packet tracing. + --ss _s_r_c_a_d_d_r Uses _s_r_c_a_d_d_r as the local IP address for all connections. + + --tt Enables packet tracing. --TT _d_i_r_e_c_t_i_o_n,_m_a_x_i_m_u_m[,_i_n_c_r_e_m_e_n_t] - Set the maximum transfer rate for _d_i_r_e_c_t_i_o_n to _m_a_x_i_m_u_m - bytes/second, and if specified, the increment to _i_n_c_r_e_m_e_n_t - bytes/second. Refer to rraattee for more information. + Set the maximum transfer rate for _d_i_r_e_c_t_i_o_n to _m_a_x_i_m_u_m + bytes/second, and if specified, the increment to _i_n_c_r_e_m_e_n_t + bytes/second. Refer to rraattee for more information. --uu _U_R_L _f_i_l_e [...] - Upload files on the command line to _U_R_L where _U_R_L is one of the - ftp URL types as supported by auto-fetch (with an optional tar- - get filename for single file uploads), and _f_i_l_e is one or more - local files to be uploaded. + Upload files on the command line to _U_R_L where _U_R_L is one of + the ftp URL types as supported by auto-fetch (with an + optional target filename for single file uploads), and _f_i_l_e + is one or more local files to be uploaded. - --vv Enable vveerrbboossee and pprrooggrreessss. This is the default if output is - to a terminal (and in the case of pprrooggrreessss, ffttpp is the fore- - ground process). Forces ffttpp to show all responses from the - remote server, as well as report on data transfer statistics. + --vv Enable vveerrbboossee and pprrooggrreessss. This is the default if output + is to a terminal (and in the case of pprrooggrreessss, ffttpp is the + foreground process). Forces ffttpp to show all responses from + the remote server, as well as report on data transfer statis- + tics. - --VV Disable vveerrbboossee and pprrooggrreessss, overriding the default of enabled - when output is to a terminal. + --VV Disable vveerrbboossee and pprrooggrreessss, overriding the default of + enabled when output is to a terminal. The client host with which ffttpp is to communicate may be specified on the command line. If this is done, ffttpp will immediately attempt to establish @@ -177,11 +181,11 @@ DDEESSCCRRIIPPTTIIOONN may be distinguished from a record delimiter only when ccrr is off. - ddeebbuugg [_d_e_b_u_g_-_v_a_l_u_e] - Toggle debugging mode. If an optional _d_e_b_u_g_-_v_a_l_u_e is speci- - fied it is used to set the debugging level. When debugging - is on, ffttpp prints each command sent to the remote machine, - preceded by the string `-->' + ffttpp__ddeebbuugg [_f_t_p___d_e_b_u_g_-_v_a_l_u_e] + Toggle debugging mode. If an optional _f_t_p___d_e_b_u_g_-_v_a_l_u_e is + specified it is used to set the debugging level. When debug- + ging is on, ffttpp prints each command sent to the remote + machine, preceded by the string `-->' ddeelleettee _r_e_m_o_t_e_-_f_i_l_e Delete the file _r_e_m_o_t_e_-_f_i_l_e on the remote machine. @@ -260,7 +264,7 @@ DDEESSCCRRIIPPTTIIOONN tree (in binary mode). hhaasshh [_s_i_z_e] - Toggle hash-sign (``#'') printing for each data block trans- + Toggle hash-sign (`#') printing for each data block trans- ferred. The size of a data block defaults to 1024 bytes. This can be changed by specifying _s_i_z_e in bytes. Enabling hhaasshh disables pprrooggrreessss. @@ -297,18 +301,23 @@ DDEESSCCRRIIPPTTIIOONN _m_a_c_r_o_-_n_a_m_e; a null line (consecutive newline characters in a file or carriage returns from the terminal) terminates macro input mode. There is a limit of 16 macros and 4096 total - characters in all defined macros. Macros remain defined - until a cclloossee command is executed. The macro processor - interprets `$' and `\' as special characters. A `$' followed - by a number (or numbers) is replaced by the corresponding - argument on the macro invocation command line. A `$' fol- - lowed by an `i' signals that macro processor that the execut- - ing macro is to be looped. On the first pass `$i' is - replaced by the first argument on the macro invocation com- - mand line, on the second pass it is replaced by the second - argument, and so on. A `\' followed by any character is - replaced by that character. Use the `\' to prevent special - treatment of the `$'. + characters in all defined macros. Macro names can be a maxi- + mum of 8 characters. Macros are only applicable to the cur- + rent session they are defined within (or if defined outside a + session, to the session invoked with the next ooppeenn command), + and remain defined until a cclloossee command is executed. To + invoke a macro, use the $$ command (see above). + + The macro processor interprets `$' and `\' as special charac- + ters. A `$' followed by a number (or numbers) is replaced by + the corresponding argument on the macro invocation command + line. A `$' followed by an `i' signals the macro processor + that the executing macro is to be looped. On the first pass + ``$i'' is replaced by the first argument on the macro invoca- + tion command line, on the second pass it is replaced by the + second argument, and so on. A `\' followed by any character + is replaced by that character. Use the `\' to prevent spe- + cial treatment of the `$'. mmddeelleettee [_r_e_m_o_t_e_-_f_i_l_e_s] Delete the _r_e_m_o_t_e_-_f_i_l_e_s on the remote machine. @@ -356,7 +365,7 @@ DDEESSCCRRIIPPTTIIOONN mmooddttiimmee _r_e_m_o_t_e_-_f_i_l_e Show the last modification time of the file on the remote - machine. + machine, in RFC2822 format. mmoorree _f_i_l_e A synonym for ppaaggee. @@ -396,19 +405,19 @@ DDEESSCCRRIIPPTTIIOONN [_I_n_p_a_t_t_e_r_n] is a template for incoming filenames (which may have already been processed according to the nnttrraannss and ccaassee settings). Variable templating is accomplished by including - the sequences `$1', `$2', ..., `$9' in _i_n_p_a_t_t_e_r_n. Use `\' to - prevent this special treatment of the `$' character. All - other characters are treated literally, and are used to + the sequences ``$1'', ``$2'', ... ``$9'' in _i_n_p_a_t_t_e_r_n. Use + `\' to prevent this special treatment of the `$' character. + All other characters are treated literally, and are used to determine the nnmmaapp [_i_n_p_a_t_t_e_r_n] variable values. For example, given _i_n_p_a_t_t_e_r_n $1.$2 and the remote file name "mydata.data", $1 would have the value "mydata", and $2 would have the value "data". The _o_u_t_p_a_t_t_e_r_n determines the resulting mapped file- - name. The sequences `$1', `$2', ...., `$9' are replaced by - any value resulting from the _i_n_p_a_t_t_e_r_n template. The - sequence `$0' is replace by the original filename. Addition- - ally, the sequence `[_s_e_q_1, _s_e_q_2]' is replaced by [_s_e_q_1] if - _s_e_q_1 is not a null string; otherwise it is replaced by _s_e_q_2. - For example, the command + name. The sequences ``$1'', ``$2'', ... ``$9'' are replaced + by any value resulting from the _i_n_p_a_t_t_e_r_n template. The + sequence ``$0'' is replaced by the original filename. Addi- + tionally, the sequence ``[_s_e_q_1, _s_e_q_2]'' is replaced by [_s_e_q_1] + if _s_e_q_1 is not a null string; otherwise it is replaced by + _s_e_q_2. For example, the command nmap $1.$2.$3 [$1,$2].[$2,file] @@ -416,9 +425,10 @@ DDEESSCCRRIIPPTTIIOONN names "myfile.data" and "myfile.data.old", "myfile.file" for the input filename "myfile", and "myfile.myfile" for the input filename ".myfile". Spaces may be included in - _o_u_t_p_a_t_t_e_r_n, as in the example: `nmap $1 sed "s/ *$//" > $1' - . Use the `\' character to prevent special treatment of the - `$','[',']', and `,' characters. + _o_u_t_p_a_t_t_e_r_n, as in the example: + nmap $1 sed s/ *$// > $1 + Use the `\' character to prevent special treatment of the + `$', `[', `]', and `,' characters. nnttrraannss [_i_n_c_h_a_r_s [_o_u_t_c_h_a_r_s]] Set or unset the filename character translation mechanism. @@ -459,7 +469,7 @@ DDEESSCCRRIIPPTTIIOONN who connects back to it. Passive mode is useful when using ffttpp through a gateway router or host that controls the direc- tionality of traffic. (Note that though FTP servers are - required to support the PASV command by RFC 1123, some do + required to support the PASV command by RFC1123, some do not.) ppddiirr [_r_e_m_o_t_e_-_p_a_t_h] @@ -770,8 +780,8 @@ AAUUTTOO--FFEETTCCHHIINNGG FFIILLEESS fer type will take place as ascii or binary (respectively). The default transfer type is binary. - In order to be compliant with RFC 1738, ffttpp interprets the _p_a_t_h - part of an ``ftp://'' auto-fetch URL as follows: + In order to be compliant with RFC3986, ffttpp interprets the _p_a_t_h part + of an ``ftp://'' auto-fetch URL as follows: ++oo The `/' immediately after the _h_o_s_t[:_p_o_r_t] is interpreted as a separator before the _p_a_t_h, and not as part of the _p_a_t_h itself. @@ -786,7 +796,7 @@ AAUUTTOO--FFEETTCCHHIINNGG FFIILLEESS the equivalent of a ccdd command without a directory name. This is unlikely to be useful. - ++oo Any `%_X_X' codes (per RFC 1738) within the path components are + ++oo Any `%_X_X' codes (per RFC3986) within the path components are decoded, with _X_X representing a character code in hexadecimal. This decoding takes place after the _p_a_t_h has been split into components, but before each component is used in the equivalent @@ -839,6 +849,15 @@ AAUUTTOO--FFEETTCCHHIINNGG FFIILLEESS file:///_p_a_t_h A local URL, copied from _/_p_a_t_h on the local host. + about:_t_o_p_i_c + Display information regarding _t_o_p_i_c; no file is retrieved for this + auto-fetched element. Supported values include: + + about:ftp Information about ffttpp. + + about:version The version of ffttpp. Useful to provide when report- + ing problems. + Unless noted otherwise above, and --oo _o_u_t_p_u_t is not given, the file is stored in the current directory as the basename(1) of _p_a_t_h. Note that if a HTTP redirect is received, the fetch is retried using the new target @@ -898,7 +917,7 @@ FFIILLEE NNAAMMIINNGG CCOONNVVEENNTTIIOONNSS example of this mechanism is: ``dir "" |more''. 3. Failing the above checks, if ``globbing'' is enabled, local file - names are expanded according to the rules used in the csh(1); c.f. + names are expanded according to the rules used in the csh(1); see the gglloobb command. If the ffttpp command expects a single local file (e.g. ppuutt), only the first filename generated by the "globbing" operation is used. @@ -973,8 +992,13 @@ TTHHEE ..nneettrrcc FFIILLEE mand functions. A macro is defined with the specified name; its contents begin with the next _._n_e_t_r_c line and continue until a blank line (consecutive new-line characters) is encountered. - If a macro named iinniitt is defined, it is automatically executed - as the last step in the auto-login process. For example, + Like the other tokens in the _._n_e_t_r_c file, a mmaaccddeeff is applica- + ble only to the mmaacchhiinnee definition preceding it. A mmaaccddeeff + entry cannot be utilized by multiple mmaacchhiinnee definitions; + rather, it must be defined following each mmaacchhiinnee it is + intended to be used with. If a macro named iinniitt is defined, it + is automatically executed as the last step in the auto-login + process. For example, default macdef init @@ -1074,8 +1098,8 @@ EENNVVIIRROONNMMEENNTT used in the first attempt to authenticate to the proxy. If ``unsafe'' URL characters are required in the username - or password (for example `@' or `/'), encode them with RFC - 1738 `%_X_X' encoding. + or password (for example `@' or `/'), encode them with + RFC3986 `%_X_X' encoding. Note that the use of a username and password in ftp_proxy and http_proxy may be incompatible with other programs @@ -1104,8 +1128,26 @@ SSEEEE AALLSSOO getservbyname(3), editrc(5), services(5), ftpd(8) SSTTAANNDDAARRDDSS - ffttpp attempts to be compliant with RFC 959, RFC 1123, RFC 1738, RFC 2068, - RFC 2389, RFC 2428, RFC 2732, and ddrraafftt--iieettff--ffttppeexxtt--mmllsstt--1111. + ffttpp attempts to be compliant with: + + RFC0959 _F_i_l_e _T_r_a_n_s_f_e_r _P_r_o_t_o_c_o_l + + RFC1123 _R_e_q_u_i_r_e_m_e_n_t_s _f_o_r _I_n_t_e_r_n_e_t _H_o_s_t_s _- _A_p_p_l_i_c_a_t_i_o_n _a_n_d _S_u_p_p_o_r_t + + RFC1635 _H_o_w _t_o _U_s_e _A_n_o_n_y_m_o_u_s _F_T_P + + RFC2389 _F_e_a_t_u_r_e _n_e_g_o_t_i_a_t_i_o_n _m_e_c_h_a_n_i_s_m _f_o_r _t_h_e _F_i_l_e _T_r_a_n_s_f_e_r + _P_r_o_t_o_c_o_l + + RFC2428 _F_T_P _E_x_t_e_n_s_i_o_n_s _f_o_r _I_P_v_6 _a_n_d _N_A_T_s + + RFC2616 _H_y_p_e_r_t_e_x_t _T_r_a_n_s_f_e_r _P_r_o_t_o_c_o_l _-_- _H_T_T_P_/_1_._1 + + RFC2822 _I_n_t_e_r_n_e_t _M_e_s_s_a_g_e _F_o_r_m_a_t + + RFC3659 _E_x_t_e_n_s_i_o_n_s _t_o _F_T_P + + RFC3986 _U_n_i_f_o_r_m _R_e_s_o_u_r_c_e _I_d_e_n_t_i_f_i_e_r _(_U_R_I_) HHIISSTTOORRYY The ffttpp command appeared in 4.2BSD. @@ -1138,4 +1180,4 @@ BBUUGGSS uses a SIIT translator for IPv6-to-IPv4 translation, ffttpp is unable to support your configuration. -NetBSD 3.0_BETA January 15, 2005 NetBSD 3.0_BETA +NetBSD 3.1.1 July 18, 2007 NetBSD 3.1.1 diff --git a/net/tnftp/files/src/ftp_var.h b/net/tnftp/files/src/ftp_var.h index 3fd33788013..78bc26159ca 100644 --- a/net/tnftp/files/src/ftp_var.h +++ b/net/tnftp/files/src/ftp_var.h @@ -1,8 +1,8 @@ -/* NetBSD: ftp_var.h,v 1.5 2005/05/11 02:41:28 lukem Exp */ -/* from NetBSD: ftp_var.h,v 1.71 2005/04/11 01:49:31 lukem Exp */ +/* $NetBSD: ftp_var.h,v 1.1.1.4 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: ftp_var.h,v 1.75 2007/07/22 05:02:50 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 @@ -108,6 +108,20 @@ #define NO_PROGRESS #endif +#if 0 /* tnftp */ + +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <poll.h> + +#include <setjmp.h> +#include <stringlist.h> + +#endif /* tnftp */ + #ifndef NO_EDITCOMPLETE #include <histedit.h> #endif /* !NO_EDITCOMPLETE */ @@ -201,7 +215,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 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 */ @@ -270,6 +284,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 */ @@ -318,7 +333,7 @@ extern struct option optiontab[]; #define FREEPTR(x) if ((x) != NULL) { free(x); (x) = NULL; } #ifdef BSD4_4 -# define HAVE_SOCKADDR_SA_LEN 1 +# define HAVE_STRUCT_SOCKADDR_SA_LEN 1 #endif #ifdef NO_LONG_LONG @@ -326,3 +341,18 @@ extern struct option optiontab[]; #else # define STRTOLL(x,y,z) strtoll(x,y,z) #endif + +#ifdef NO_DEBUG +#define DPRINTF(...) +#define DWARN(...) +#else +#define DPRINTF(...) if (ftp_debug) (void)fprintf(ttyout, __VA_ARGS__) +#define DWARN(...) if (ftp_debug) warn(__VA_ARGS__) +#endif + +#ifdef NO_USAGE +void xusage(void); +#define UPRINTF(...) xusage() +#else +#define UPRINTF(...) (void)fprintf(ttyout, __VA_ARGS__) +#endif diff --git a/net/tnftp/files/src/main.c b/net/tnftp/files/src/main.c index 67462769552..704cc8ed9d3 100644 --- a/net/tnftp/files/src/main.c +++ b/net/tnftp/files/src/main.c @@ -1,5 +1,5 @@ -/* NetBSD: main.c,v 1.11 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: main.c,v 1.97 2005/06/10 00:18:46 lukem Exp */ +/* $NetBSD: main.c,v 1.1.1.6 2007/08/06 04:33:23 lukem Exp $ */ +/* from NetBSD: main.c,v 1.105 2007/05/22 05:16:48 lukem Exp */ /*- * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. @@ -95,11 +95,44 @@ * SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94"; +#else +__RCSID(" NetBSD: main.c,v 1.105 2007/05/22 05:16:48 lukem Exp "); +#endif +#endif /* not lint */ + /* * FTP User Program -- Command Interface. */ - -#include "tnftp.h" +#include <sys/types.h> +#include <sys/socket.h> + +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <locale.h> + +#endif /* tnftp */ #define GLOBAL /* force GLOBAL decls in ftp_var.h to be declared */ #include "ftp_var.h" @@ -113,18 +146,19 @@ 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; -#if 0 /* XXX */ + tzset(); +#if 0 /* tnftp */ /* XXX */ setlocale(LC_ALL, ""); -#endif +#endif /* tnftp */ setprogname(argv[0]); sigint_raised = 0; @@ -166,6 +200,7 @@ main(int argc, char *argv[]) epsv4 = 0; #endif epsv4bad = 0; + src_addr = NULL; upload_path = NULL; isupload = 0; reply_callback = NULL; @@ -184,15 +219,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) @@ -205,7 +240,7 @@ main(int argc, char *argv[]) if (rcvbuf_size > 8 * 1024 * 1024) rcvbuf_size = 8 * 1024 * 1024; - marg_sl = xsl_init(); + marg_sl = ftp_sl_init(); if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = _PATH_TMP; @@ -223,7 +258,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) { @@ -264,7 +299,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; @@ -289,7 +324,7 @@ main(int argc, char *argv[]) case 'd': options |= SO_DEBUG; - debug++; + ftp_debug++; break; case 'e': @@ -339,19 +374,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; @@ -364,11 +403,12 @@ main(int argc, char *argv[]) /* look for `dir,max[,incr]' */ targc = 0; targv[targc++] = "-T"; - oac = xstrdup(optarg); + oac = ftp_strdup(optarg); while ((cp = strsep(&oac, ",")) != NULL) { if (*cp == '\0') { - warnx("bad throttle value: %s", optarg); + warnx("Bad throttle value `%s'", + optarg); usage(); /* NOTREACHED */ } @@ -386,7 +426,7 @@ main(int argc, char *argv[]) { isupload = 1; interactive = 0; - upload_path = xstrdup(optarg); + upload_path = ftp_strdup(optarg); break; } @@ -413,6 +453,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. */ @@ -421,7 +477,7 @@ main(int argc, char *argv[]) anonuser = "anonymous"; cp = getenv("HOME"); if (! EMPTYSTRING(cp)) - localhome = xstrdup(cp); + localhome = ftp_strdup(cp); pw = NULL; cp = getlogin(); if (cp != NULL) @@ -430,8 +486,8 @@ main(int argc, char *argv[]) pw = getpwuid(getuid()); if (pw != NULL) { if (localhome == NULL && !EMPTYSTRING(pw->pw_dir)) - localhome = xstrdup(pw->pw_dir); - localname = xstrdup(pw->pw_name); + localhome = ftp_strdup(pw->pw_dir); + localname = ftp_strdup(pw->pw_name); anonuser = localname; } if (netrc[0] == '\0' && localhome != NULL) { @@ -443,7 +499,7 @@ main(int argc, char *argv[]) } } if (localhome == NULL) - localhome = xstrdup("/"); + localhome = ftp_strdup("/"); /* * Every anonymous FTP server I've encountered will accept the @@ -453,7 +509,7 @@ main(int argc, char *argv[]) * - thorpej@NetBSD.org */ len = strlen(anonuser) + 2; - anonpass = xmalloc(len); + anonpass = ftp_malloc(len); (void)strlcpy(anonpass, anonuser, len); (void)strlcat(anonpass, "@", len); @@ -480,11 +536,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); @@ -572,7 +623,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); @@ -593,7 +644,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); @@ -608,7 +659,9 @@ cmdscanner(void) { struct cmd *c; char *p; +#ifndef NO_EDITCOMPLETE int ch; +#endif size_t num; for (;;) { @@ -620,8 +673,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 */ @@ -754,7 +807,7 @@ makeargv(void) marg_sl->sl_cur = 0; /* reset to start of marg_sl */ for (margc = 0; ; margc++) { argp = slurpstring(); - xsl_add(marg_sl, argp); + ftp_sl_add(marg_sl, argp); if (argp == NULL) break; } @@ -928,19 +981,19 @@ help(int argc, char *argv[]) cmd = argv[0]; isusage = (strcmp(cmd, "usage") == 0); if (argc == 0 || (isusage && argc == 1)) { - fprintf(ttyout, "usage: %s [command [...]]\n", cmd); + UPRINTF("usage: %s [command [...]]\n", cmd); return; } if (argc == 1) { StringList *buf; - buf = xsl_init(); + buf = ftp_sl_init(); fprintf(ttyout, "%sommands may be abbreviated. Commands are:\n\n", proxy ? "Proxy c" : "C"); for (c = cmdtab; (p = c->c_name) != NULL; c++) if (!proxy || c->c_proxy) - xsl_add(buf, p); + ftp_sl_add(buf, p); list_vertical(buf); sl_free(buf, 0); return; @@ -991,11 +1044,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 */ } @@ -1021,8 +1074,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/net/tnftp/files/src/progressbar.c b/net/tnftp/files/src/progressbar.c index f9b1216ce8f..317262b98fd 100644 --- a/net/tnftp/files/src/progressbar.c +++ b/net/tnftp/files/src/progressbar.c @@ -1,8 +1,8 @@ -/* NetBSD: progressbar.c,v 1.9 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: progressbar.c,v 1.10 2005/06/09 16:38:29 lukem Exp */ +/* $NetBSD: progressbar.c,v 1.1.1.5 2007/08/06 04:33:24 lukem Exp $ */ +/* from NetBSD: progressbar.c,v 1.17 2007/05/05 18:09:24 martin 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 @@ -37,11 +37,32 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID(" NetBSD: progressbar.c,v 1.17 2007/05/05 18:09:24 martin Exp "); +#endif /* not lint */ + /* * FTP User Program -- Misc support routines */ +#include <sys/types.h> +#include <sys/param.h> -#include "tnftp.h" +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <tzfile.h> +#include <unistd.h> + +#endif /* tnftp */ #include "progressbar.h" @@ -81,10 +102,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. @@ -111,8 +145,7 @@ progressmeter(int flag) struct timeval td; off_t abbrevsize, bytespersec; double elapsed; - int ratio, i, remaining; - size_t barlength; + int ratio, i, remaining, barlength; /* * Work variables for progress bar. @@ -126,7 +159,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 @@ -206,7 +239,7 @@ progressmeter(int flag) */ barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD; if (prefix) - barlength -= strlen(prefix); + barlength -= (int)strlen(prefix); if (barlength > 0) { i = barlength * ratio / 100; len += snprintf(buf + len, BUFLEFT, @@ -215,12 +248,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; - len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ", + if (i == NSUFFIXES) + i--; + 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); @@ -231,13 +265,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) { @@ -323,12 +357,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; - len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)", + if (i == NSUFFIXES) + i--; + 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) { @@ -457,7 +493,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/net/tnftp/files/src/progressbar.h b/net/tnftp/files/src/progressbar.h index a3f80d179e9..d9bf1813be5 100644 --- a/net/tnftp/files/src/progressbar.h +++ b/net/tnftp/files/src/progressbar.h @@ -1,4 +1,4 @@ -/* NetBSD: progressbar.h,v 1.5 2005/05/11 02:41:28 lukem Exp */ +/* $NetBSD: progressbar.h,v 1.1.1.4 2007/08/06 04:33:24 lukem Exp $ */ /* from NetBSD: progressbar.h,v 1.5 2005/02/10 16:00:38 jmc Exp */ /*- @@ -91,19 +91,19 @@ void ptransfer(int); # define ULLFP(x) "%" x "lu" # define ULLT unsigned long #else -#if HAVE_PRINTF_QD +#if defined(HAVE_PRINTF_QD) # define LLF "%qd" # define LLFP(x) "%" x "qd" # define LLT long long # define ULLF "%qu" # define ULLFP(x) "%" x "qu" # define ULLT unsigned long long -#else +#else /* !defined(HAVE_PRINTF_QD) */ # define LLF "%lld" # define LLFP(x) "%" x "lld" # define LLT long long # define ULLF "%llu" # define ULLFP(x) "%" x "llu" # define ULLT unsigned long long -#endif +#endif /* !defined(HAVE_PRINTF_QD) */ #endif diff --git a/net/tnftp/files/src/ruserpass.c b/net/tnftp/files/src/ruserpass.c index 491eb9565f9..24db485e816 100644 --- a/net/tnftp/files/src/ruserpass.c +++ b/net/tnftp/files/src/ruserpass.c @@ -1,5 +1,5 @@ -/* NetBSD: ruserpass.c,v 1.6 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: ruserpass.c,v 1.30 2005/06/10 00:18:47 lukem Exp */ +/* $NetBSD: ruserpass.c,v 1.1.1.5 2007/08/06 04:33:24 lukem Exp $ */ +/* from NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp */ /* * Copyright (c) 1985, 1993, 1994 @@ -32,6 +32,31 @@ #include "tnftp.h" +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; +#else +__RCSID(" NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp "); +#endif +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#endif /* tnftp */ + #include "ftp_var.h" static int token(void); @@ -75,7 +100,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) @@ -84,7 +109,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; @@ -92,7 +117,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 @@ -116,12 +143,15 @@ 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 = xstrdup(tokval); + *aname = ftp_strdup(tokval); else { if (strcmp(*aname, tokval)) goto next; @@ -132,22 +162,26 @@ 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) - *apass = xstrdup(tokval); + 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) - *aacct = xstrdup(tokval); + if ((t = token()) == -1) + goto bad; + if (t && *aacct == NULL) + *aacct = ftp_strdup(tokval); break; case MACDEF: if (proxy) { @@ -207,9 +241,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'; } @@ -222,12 +260,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: @@ -253,16 +293,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/net/tnftp/files/src/util.c b/net/tnftp/files/src/util.c index 6862fd4f316..add29b6c453 100644 --- a/net/tnftp/files/src/util.c +++ b/net/tnftp/files/src/util.c @@ -1,8 +1,8 @@ -/* NetBSD: util.c,v 1.14 2005/06/10 04:05:01 lukem Exp */ -/* from NetBSD: util.c,v 1.129 2005/06/10 00:18:47 lukem Exp */ +/* $NetBSD: util.c,v 1.1.1.6 2007/08/06 04:33:24 lukem Exp $ */ +/* from NetBSD: util.c,v 1.143 2007/05/24 05:05:19 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 @@ -70,11 +70,43 @@ * SUCH DAMAGE. */ +#include "tnftp.h" + +#if 0 /* tnftp */ + +#include <sys/cdefs.h> +#ifndef lint +__RCSID(" NetBSD: util.c,v 1.143 2007/05/24 05:05:19 lukem Exp "); +#endif /* not lint */ + /* * FTP User Program -- Misc support routines */ - -#include "tnftp.h" +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/ftp.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <glob.h> +#include <signal.h> +#include <libgen.h> +#include <limits.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <time.h> +#include <tzfile.h> +#include <unistd.h> + +#endif /* tnftp */ #include "ftp_var.h" @@ -99,7 +131,7 @@ setpeer(int argc, char *argv[]) (void)another(&argc, &argv, "to"); if (argc < 2 || argc > 3) { usage: - fprintf(ttyout, "usage: %s host-name [port]\n", argv[0]); + UPRINTF("usage: %s host-name [port]\n", argv[0]); code = -1; return; } @@ -112,7 +144,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); @@ -150,7 +182,7 @@ parse_feat(const char *line) /* * work-around broken ProFTPd servers that can't - * even obey RFC 2389. + * even obey RFC2389. */ while (*line && isspace((int)*line)) line++; @@ -177,7 +209,7 @@ getremoteinfo(void) int overbose, i; overbose = verbose; - if (debug == 0) + if (ftp_debug == 0) verbose = -1; /* determine remote system type */ @@ -243,7 +275,8 @@ getremoteinfo(void) features[FEAT_FEAT] = 1; } else features[FEAT_FEAT] = 0; - if (debug) { +#ifndef NO_DEBUG + if (ftp_debug) { #define DEBUG_FEAT(x) fprintf(ttyout, "features[" #x "] = %d\n", features[(x)]) DEBUG_FEAT(FEAT_FEAT); DEBUG_FEAT(FEAT_MDTM); @@ -253,6 +286,7 @@ getremoteinfo(void) DEBUG_FEAT(FEAT_TVFS); #undef DEBUG_FEAT } +#endif reply_callback = NULL; verbose = overbose; @@ -352,29 +386,29 @@ 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; aflag = rval = 0; user = pass = acct = NULL; if (luser) - user = xstrdup(luser); + user = ftp_strdup(luser); if (lpass) - pass = xstrdup(lpass); + pass = ftp_strdup(lpass); - if (debug) - fprintf(ttyout, "ftp_login: user `%s' pass `%s' host `%s'\n", - user ? user : "<null>", pass ? pass : "<null>", - host ? host : "<null>"); + DPRINTF("ftp_login: user `%s' pass `%s' host `%s'\n", + user ? user : "<null>", pass ? pass : "<null>", + host ? host : "<null>"); /* * Set up arguments for an anonymous FTP session, if necessary. */ if (anonftp) { FREEPTR(user); - user = xstrdup("anonymous"); /* as per RFC 1635 */ + user = ftp_strdup("anonymous"); /* as per RFC1635 */ FREEPTR(pass); - pass = xstrdup(getoptionvalue("anonpass")); + pass = ftp_strdup(getoptionvalue("anonpass")); } if (ruserpass(host, &user, &pass, &acct) < 0) { @@ -394,9 +428,9 @@ ftp_login(const char *host, const char *luser, const char *lpass) code = -1; goto cleanup_ftp_login; } else if (nlen == 0) { - user = xstrdup(localname); + user = ftp_strdup(localname); } else { - user = xstrdup(tmp); + user = ftp_strdup(tmp); } } @@ -405,7 +439,7 @@ ftp_login(const char *host, const char *luser, const char *lpass) size_t len; len = strlen(user) + 1 + strlen(host) + 1; - nuser = xmalloc(len); + nuser = ftp_malloc(len); (void)strlcpy(nuser, user, len); (void)strlcat(nuser, "@", len); (void)strlcat(nuser, host, len); @@ -417,7 +451,9 @@ ftp_login(const char *host, const char *luser, const char *lpass) if (n == CONTINUE) { if (pass == NULL) { p = getpass("Password: "); - pass = xstrdup(p); + if (p == NULL) + p = emptypass; + pass = ftp_strdup(p); memset(p, 0, strlen(p)); } n = command("PASS %s", pass); @@ -427,11 +463,13 @@ ftp_login(const char *host, const char *luser, const char *lpass) aflag++; if (acct == NULL) { p = getpass("Account: "); - acct = xstrdup(p); + 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); @@ -439,11 +477,11 @@ 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; - username = xstrdup(user); + username = ftp_strdup(user); if (proxy) goto cleanup_ftp_login; @@ -466,7 +504,7 @@ ftp_login(const char *host, const char *luser, const char *lpass) memset(pass, 0, strlen(pass)); FREEPTR(pass); if (acct != NULL) - memset(acct, 0, strlen(pass)); + memset(acct, 0, strlen(acct)); FREEPTR(acct); return (rval); } @@ -546,7 +584,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); @@ -573,12 +611,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); } } @@ -607,16 +643,16 @@ globulize(const char *pattern) char *p; if (!doglob) - return (xstrdup(pattern)); + return (ftp_strdup(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); } - p = xstrdup(gl.gl_pathv[0]); + p = ftp_strdup(gl.gl_pathv[0]); globfree(&gl); return (p); } @@ -632,7 +668,7 @@ remotesize(const char *file, int noisy) overbose = verbose; size = -1; - if (debug == 0) + if (ftp_debug == 0) verbose = -1; if (! features[FEAT_SIZE]) { if (noisy) @@ -654,7 +690,7 @@ remotesize(const char *file, int noisy) } else { if (r == ERROR && code == 500 && features[FEAT_SIZE] == -1) features[FEAT_SIZE] = 0; - if (noisy && debug == 0) { + if (noisy && ftp_debug == 0) { fputs(reply_string, ttyout); putc('\n', ttyout); } @@ -676,7 +712,7 @@ remotemodtime(const char *file, int noisy) overbose = verbose; ocode = code; rtime = -1; - if (debug == 0) + if (ftp_debug == 0) verbose = -1; if (! features[FEAT_MDTM]) { if (noisy) @@ -688,7 +724,6 @@ remotemodtime(const char *file, int noisy) if (r == COMPLETE) { struct tm timebuf; char *timestr, *frac; - int yy, mo, day, hour, min, sec; /* * time-val = 14DIGIT [ "." 1*DIGIT ] @@ -720,33 +755,28 @@ remotemodtime(const char *file, int noisy) timestr[1] = '0'; fprintf(ttyout, "Converted to `%s'\n", timestr); } + memset(&timebuf, 0, sizeof(timebuf)); if (strlen(timestr) != 14 || - sscanf(timestr, "%04d%02d%02d%02d%02d%02d", - &yy, &mo, &day, &hour, &min, &sec) != 6) { + (strptime(timestr, "%Y%m%d%H%M%S", &timebuf) == NULL)) { bad_parse_time: fprintf(ttyout, "Can't parse time `%s'.\n", timestr); goto cleanup_parse_time; } - memset(&timebuf, 0, sizeof(timebuf)); - timebuf.tm_sec = sec; - timebuf.tm_min = min; - timebuf.tm_hour = hour; - timebuf.tm_mday = day; - timebuf.tm_mon = mo - 1; - timebuf.tm_year = yy - TM_YEAR_BASE; timebuf.tm_isdst = -1; rtime = timegm(&timebuf); if (rtime == -1) { - if (noisy || debug != 0) + if (noisy || ftp_debug != 0) goto bad_parse_time; else goto cleanup_parse_time; - } else if (debug) - fprintf(ttyout, "parsed date as: %s", ctime(&rtime)); + } else + DPRINTF("parsed date `%s' as " LLF ", %s", + timestr, (LLT)rtime, + rfc2822time(localtime(&rtime))); } else { if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1) features[FEAT_MDTM] = 0; - if (noisy && debug == 0) { + if (noisy && ftp_debug == 0) { fputs(reply_string, ttyout); putc('\n', ttyout); } @@ -759,6 +789,21 @@ remotemodtime(const char *file, int noisy) } /* + * Format tm in an RFC2822 compatible manner, with a trailing \n. + * Returns a pointer to a static string containing the result. + */ +const char * +rfc2822time(const struct tm *tm) +{ + static char result[50]; + + if (strftime(result, sizeof(result), + "%a, %d %b %Y %H:%M:%S %z\n", tm) == 0) + errx(1, "Can't convert RFC2822 time: buffer too small"); + return result; +} + +/* * Update global `localcwd', which contains the state of the local cwd */ void @@ -767,8 +812,7 @@ updatelocalcwd(void) if (getcwd(localcwd, sizeof(localcwd)) == NULL) localcwd[0] = '\0'; - if (debug) - fprintf(ttyout, "got localcwd as `%s'\n", localcwd); + DPRINTF("got localcwd as `%s'\n", localcwd); } /* @@ -782,7 +826,7 @@ updateremotecwd(void) overbose = verbose; ocode = code; - if (debug == 0) + if (ftp_debug == 0) verbose = -1; if (command("PWD") != COMPLETE) goto badremotecwd; @@ -800,8 +844,7 @@ updateremotecwd(void) remotecwd[i] = *cp; } remotecwd[i] = '\0'; - if (debug) - fprintf(ttyout, "got remotecwd as `%s'\n", remotecwd); + DPRINTF("got remotecwd as `%s'\n", remotecwd); goto cleanupremotecwd; badremotecwd: remotecwd[0]='\0'; @@ -821,7 +864,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) @@ -878,10 +921,12 @@ list_vertical(StringList *sl) putc('\n', ttyout); break; } - w = strlen(p); - while (w < width) { - w = (w + 8) &~ 7; - (void)putc('\t', ttyout); + if (p) { + w = strlen(p); + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } } } } @@ -1026,11 +1071,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); } /* @@ -1186,7 +1231,7 @@ parseport(const char *port, int defport) long nport; char *p, *ep; - p = xstrdup(port); + p = ftp_strdup(port); nport = strtol(p, &ep, 10); if (*ep != '\0' && ep == p) { struct servent *svp; @@ -1229,8 +1274,7 @@ isipv6addr(const char *addr) rv = 1; freeaddrinfo(res); } - if (debug) - fprintf(ttyout, "isipv6addr: got %d for %s\n", rv, addr); + DPRINTF("isipv6addr: got %d for %s\n", rv, addr); #endif return (rv == 1) ? 1 : 0; } @@ -1285,29 +1329,65 @@ 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 -xconnect(int sock, const struct sockaddr *name, socklen_t namelen) +ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen) { int flags, rv, timeout, error; 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 */ @@ -1321,8 +1401,11 @@ xconnect(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 { @@ -1336,34 +1419,39 @@ xconnect(int sock, const struct sockaddr *name, socklen_t namelen) timeout = INFTIM; } pfd[0].revents = 0; - rv = xpoll(pfd, 1, timeout); + rv = ftp_poll(pfd, 1, timeout); /* loop until poll ! EINTR */ } while (rv == -1 && errno == EINTR); 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; } @@ -1371,7 +1459,7 @@ xconnect(int sock, const struct sockaddr *name, socklen_t namelen) * Internal version of listen(2); sets socket buffer sizes first. */ int -xlisten(int sock, int backlog) +ftp_listen(int sock, int backlog) { setupsockbufsize(sock); @@ -1383,12 +1471,13 @@ xlisten(int sock, int backlog) * on platforms without the former. */ int -xpoll(struct pollfd *fds, int nfds, int timeout) +ftp_poll(struct pollfd *fds, int nfds, int timeout) { -#if HAVE_POLL +#if defined(HAVE_POLL) return poll(fds, nfds, timeout); -#elif HAVE_SELECT /* implement poll(2) using select(2) */ +#elif defined(HAVE_SELECT) + /* implement poll(2) using select(2) */ fd_set rset, wset, xset; const int rsetflags = POLLIN | POLLRDNORM; const int wsetflags = POLLOUT | POLLWRNORM; @@ -1449,7 +1538,7 @@ xpoll(struct pollfd *fds, int nfds, int timeout) * malloc() with inbuilt error checking */ void * -xmalloc(size_t size) +ftp_malloc(size_t size) { void *p; @@ -1463,7 +1552,7 @@ xmalloc(size_t size) * sl_init() with inbuilt error checking */ StringList * -xsl_init(void) +ftp_sl_init(void) { StringList *p; @@ -1477,7 +1566,7 @@ xsl_init(void) * sl_add() with inbuilt error checking */ void -xsl_add(StringList *sl, char *i) +ftp_sl_add(StringList *sl, char *i) { if (sl_add(sl, i) == -1) @@ -1488,12 +1577,12 @@ xsl_add(StringList *sl, char *i) * strdup() with inbuilt error checking */ char * -xstrdup(const char *str) +ftp_strdup(const char *str) { char *s; if (str == NULL) - errx(1, "xstrdup() 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"); |