debian/0000755000000000000000000000000012057163567007202 5ustar debian/source/0000755000000000000000000000000011354404035010465 5ustar debian/source/format0000644000000000000000000000001411403407134011671 0ustar 3.0 (quilt) debian/dirs0000644000000000000000000000005611253430150010045 0ustar usr/bin usr/share/man/man1 usr/share/man/man5 debian/rules0000755000000000000000000000427512057163454010265 0ustar #!/usr/bin/make -f # $Id: rules,v 1.9 2001/12/11 09:03:39 herbert Exp $ # Adapted for netkit-ftp. Copyright 1999 by Herbert Xu. # Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 DEFS := -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 CFLAGS += $(shell dpkg-buildflags --get CFLAGS) CPPFLAGS += $(shell dpkg-buildflags --get CPPFLAGS) LDFLAGS += $(shell dpkg-buildflags --get LDFLAGS) DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) CROSS := else CROSS := CC=$(DEB_HOST_GNU_TYPE)-gcc endif build: build-stamp build-stamp: dh_testdir if [ ! -f MCONFIG ]; then \ ./configure; \ sed -e 's;^CFLAGS=\(.*\)$$;CFLAGS= -g $(DEFS) -fno-strict-aliasing $(CFLAGS) $(CPPFLAGS) \1;' \ -e 's;^LDFLAGS=\(.*\)$$;& $(LDFLAGS);' \ MCONFIG > MCONFIG.new; \ mv MCONFIG.new MCONFIG; \ fi $(MAKE) $(CROSS) touch build-stamp clean: dh_testdir dh_testroot rm -f build-stamp install-stamp [ ! -f MCONFIG ] || $(MAKE) distclean dh_clean install: install-stamp install-stamp: build-stamp dh_testdir dh_testroot dh_prep dh_installdirs $(MAKE) INSTALLROOT=`pwd`/debian/ftp MANDIR=/usr/share/man install mv debian/ftp/usr/bin/ftp debian/ftp/usr/bin/netkit-ftp ln -sf netkit-ftp debian/ftp/usr/bin/pftp mv debian/ftp/usr/share/man/man1/ftp.1 \ debian/ftp/usr/share/man/man1/netkit-ftp.1 ln -sf netkit-ftp.1 debian/ftp/usr/share/man/man1/pftp.1 touch install-stamp # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install # dh_testversion dh_testdir dh_testroot dh_installdocs dh_installexamples dh_installmenu dh_installcron dh_installman dh_installchangelogs ChangeLog dh_link dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb source diff: @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install debian/README.Debian0000644000000000000000000000173011576766446011256 0ustar Modified use of SYST requests ----------------------------- The legacy mode, be it with 'auto-login' or not, was to issue immediately a SYST request to the server, expecting information as to the 8-bit capabilities of the host. Since some FTP servers still are built to reject such early requests, until a valid user had been established with the client side, the old behaviour caused annoying error response. These could even disturb the use of intermediary proxy servers. As of package 'ftp_0.17-25' this behaviour has been intention- ally changed, sending SYST only with auto-login, or when issuing the commands 'user' and 'system'. A code analysis could uncover no ill effects of this step. Keep in mind that other FTP client software continue the legacy mode, such as OpenBSD, while yet others have removed it, like FreeBSD. Still others issue a SYST request, but suppress any returned reject message. The client available as 'inetutils-ftp' shows this latter behaviour. debian/prerm0000644000000000000000000000030311354404035010231 0ustar #!/bin/sh # $Id: prerm,v 1.2 2001/02/24 13:03:29 herbert Exp $ set -e if [ "$1" = remove ] || [ "$1" = deconfigure ]; then update-alternatives --remove ftp /usr/bin/netkit-ftp fi #DEBHELPER# debian/changelog0000644000000000000000000002707312057163546011062 0ustar netkit-ftp (0.17-28) unstable; urgency=low * Patch from Colin Watson to fix cross-building. (Closes: #695007) -- Alberto Gonzalez Iniesta Mon, 03 Dec 2012 18:53:56 +0100 netkit-ftp (0.17-27) unstable; urgency=low * Support large files on 32-bit architectures: * Solution identified by Martin Hicks. (Closes: #671873) + debian/patches/060_full_offset_range.diff: New file. * debian/rules: Hardening via dpkg-buildflags. * debian/control: Standards 3.9.3, no changes. + Building now depends on dpkg-dev (>= 1.15.7). * Tiny description errors: + debian/patches/010_patches_in_sarge.diff: Updated. -- Mats Erik Andersson Wed, 23 May 2012 20:08:11 +0200 netkit-ftp (0.17-26) unstable; urgency=low * Support GNU/Hurd: + debian/patches/050_support_gnu_hurd.diff: New file. * Simplify dynamic linking: + debian/control: No build dependency on libncurses-dev. + debian/patches/052_no_termcap_linking.diff: New file. -- Mats Erik Andersson Wed, 28 Mar 2012 01:29:24 +0200 netkit-ftp (0.17-25) unstable; urgency=low * Prevent SYST request in non-auto-login. (Closes: #611284) + debian/patches/043_tune_non_autologin.diff: New file. + debian/README.Debian: New file, commenting on this change. * Missing line break. (Closes: #630524) + debian/patches/040_ipv6_ftp_c.diff: Updated patch. * debian/control: Make description conform to policy. * debian/copyright: Apply versioned reference to format specs. -- Mats Erik Andersson Sat, 18 Jun 2011 02:36:02 +0200 netkit-ftp (0.17-24) unstable; urgency=low * Standards version 3.9.2. + debian/copyright: Include explicit BSD license text. * Copyright reformulated based on DEP-5. * Code simplification in IPv6 extension patch. + debian/patches/040_ipv6_ftp_c.diff: Updated patch. * Implement user commands in executable. + debian/patches/041_user_address_commands.diff: New file. -- Mats Erik Andersson Tue, 19 Apr 2011 22:47:52 +0200 netkit-ftp (0.17-23) unstable; urgency=low [Mats Erik Andersson] * Rework error recovery. (Closes: #582598) + 040_ipv6_ftp_c.diff: Updated file. + Avoid double free errors by freeing immediately at an intermediary error. + Conditional use of IP_TOS for GNU/kfreebsd. * debian/copyright: Explicit licensing for the IPv6 coding. * debian/rules: Added compiler flag '-fno-strict-aliasing'. -- Mats Erik Andersson Tue, 25 May 2010 23:50:59 +0200 netkit-ftp (0.17-22) unstable; urgency=low * Changes by Mats Erik Andersson. - Updated 040_ipv6_ftp_c.diff to fix double free error (Closes: #579532) * Added Mats to the Uploaders field. -- Alberto Gonzalez Iniesta Tue, 11 May 2010 12:01:39 +0200 netkit-ftp (0.17-21) unstable; urgency=low * Updated 040_ipv6_ftp_c.diff with Mats' latest patch -- Alberto Gonzalez Iniesta Tue, 30 Mar 2010 16:45:04 +0200 netkit-ftp (0.17-20) unstable; urgency=low * Changes by Mats Erik Andersson. Thanks for the HUGE patch! - Migrate to format "3.0 (quilt)". - debian/control: Adding ${misc:Depends} due to Debhelper. - debian/substvars: Deleted file. - debian/watch: New file. - Extract in-situ patches. Deposited in debian/patches/: + 010_patches_in_sarge.diff + 020_optional_stripping.diff + 025_long_cmd_overflow.diff + 030_argv_handling.diff - [lintian] New patch 035_lintian_pedantic.diff. - New patch for IPv6-capability: 040_ipv6_ftp_c.diff (Closes: #228752) - [lintian] maintainer-script-without-set-e: debian/{postinst,prerm} * Bumped Standards-Version to 3.8.4.0. -- Alberto Gonzalez Iniesta Tue, 30 Mar 2010 16:19:20 +0200 netkit-ftp (0.17-19) unstable; urgency=low * Patched main.c to fix memory management on command line arguments. Thanks a lot to Mark Calderbank for the patch. (Closes: #508378, #505533, #510009) * debian/control: replaced libreadline5-dev with libreadline-dev * Moved to debhelper compat 7 * Bumped Standards-Version to 3.8.3. -- Alberto Gonzalez Iniesta Mon, 14 Sep 2009 13:35:40 +0200 netkit-ftp (0.17-18) unstable; urgency=low * Clean patch applied in previous version. Thanks Steve for helping again with this. -- Alberto Gonzalez Iniesta Wed, 26 Mar 2008 18:31:12 +0100 netkit-ftp (0.17-17) unstable; urgency=low * Applied patch by Steve Kemp to fix buffer overflow in ftp commands. (Closes: #391207, #407924) Thanks a lot Steve for looking into this. * Removed stripping from Makefile. Added it as an option in debian/rules. (Closes: #437615) * Bumped Standards-Version to 3.7.3. Did some cleaning. -- Alberto Gonzalez Iniesta Fri, 21 Mar 2008 18:14:02 +0100 netkit-ftp (0.17-16) unstable; urgency=low * Build with libreadline5-dev again. Don't know how libreadline4-dev managed to get back to debian/control. (Closes: #340302) -- Alberto Gonzalez Iniesta Tue, 22 Nov 2005 19:57:36 +0100 netkit-ftp (0.17-15) unstable; urgency=low * debian/control: Added Depends: on netbase (Closes: #340082) -- Alberto Gonzalez Iniesta Mon, 21 Nov 2005 10:18:15 +0100 netkit-ftp (0.17-14) unstable; urgency=low * Rebuild with libreadline5-dev (Closes: #326364, #336572) * Removed /usr/share/doc/ftp/README since it didn't contain useful information. (Closes:#323231) * Bumped Standards-Version to 3.6.2.0, no change. * Moved to debhelper compatibility 4. Created debian/compat. -- Alberto Gonzalez Iniesta Mon, 14 Nov 2005 16:25:56 +0100 netkit-ftp (0.17-13) unstable; urgency=low * New maintainer. * debian/control. Build-Depends: Added libreadline4-dev as alternative to libreadline-dev * debian/control. Removed full stop from package description to make lintian happy. * debian/control. Bumped Standards-Version to 3.6.1.0, no change. -- Alberto Gonzalez Iniesta Sat, 12 Mar 2005 12:15:12 +0100 netkit-ftp (0.17-12) unstable; urgency=low * New maintainer. (Closes: #249706) - control (Maintainer): Set myself. -- Robert Millan Wed, 19 May 2004 02:09:50 +0200 netkit-ftp (0.17-11) unstable; urgency=low * Added netrc(5) reference to ftp(1). * Added port to SYNOPSIS in ftp(1) (closes: #191497). -- Herbert Xu Sun, 29 Jun 2003 15:37:35 +1000 netkit-ftp (0.17-10) unstable; urgency=low * Fixed LFS problem with ptransfer bytes count (closes: #143469). -- Herbert Xu Fri, 19 Apr 2002 19:27:58 +1000 netkit-ftp (0.17-9) unstable; urgency=low * Fixed more LFS issues (Hiroyuki YAMAMO, #126521). -- Herbert Xu Fri, 28 Dec 2001 20:05:07 +1100 netkit-ftp (0.17-8) unstable; urgency=low * Built with support for large files. -- Herbert Xu Tue, 11 Dec 2001 19:02:28 +1100 netkit-ftp (0.17-7) unstable; urgency=low * Moved second entry in NAME of netrc(5) to SYNOPSIS (closes: #99527). -- Herbert Xu Thu, 14 Jun 2001 19:12:49 +1000 netkit-ftp (0.17-6) unstable; urgency=low * No longer provides ftp-client. * Check for NULL pointers in abort_remote(). -- Herbert Xu Wed, 30 May 2001 19:22:30 +1000 netkit-ftp (0.17-5) unstable; urgency=low * Provide ftp-client (closes: #86782). * Check cin and cout at the top of getreply() (closes: #87845). -- Herbert Xu Wed, 28 Feb 2001 20:37:58 +1100 netkit-ftp (0.17-4) unstable; urgency=low * Added a missing terminating NUL in quote1(). -- Herbert Xu Mon, 9 Oct 2000 18:59:21 +1100 netkit-ftp (0.17-3) unstable; urgency=low * Added build-time dependency on debhelper (closes: #69103). * Replace control characters by ? on stdout if it is a tty. Also configurable via qc (closes: #69712). -- Herbert Xu Sat, 26 Aug 2000 12:41:30 +1000 netkit-ftp (0.17-2) unstable; urgency=low * Empty lines no longer cause ftp to exit. * Protect obstack_free(3) with INTOFF/INTON. -- Herbert Xu Sat, 12 Aug 2000 11:20:55 +1000 netkit-ftp (0.17-1) unstable; urgency=low * New upstream release. * Use glob(3). * Use obstacks. -- Herbert Xu Thu, 10 Aug 2000 20:39:09 +1000 netkit-ftp (0.16-8) unstable; urgency=low * Fixed an incorrect call to command() in quote1() (closes: #66901). -- Herbert Xu Sat, 8 Jul 2000 12:14:59 +1000 netkit-ftp (0.16-7) unstable; urgency=low * The pipeprotect() problem also affected globulize(). So instead of having them always return malloced memory, the result is now checked to see if it is malloced or not. This fixes a core dump observed by Jeff Lessem (closes: #63656). * Added code to protect globulize() in ls(). * Removed duplicate globulize() calls in ls(). -- Herbert Xu Sun, 14 May 2000 10:28:34 +1000 netkit-ftp (0.16-6) unstable; urgency=low * pipeprotect() now always returns malloced memory. This fixes a core dump reported by Mike Baker. -- Herbert Xu Mon, 1 May 2000 15:20:30 +1000 netkit-ftp (0.16-5) unstable; urgency=low * An attempt to fix some SIGINT races, a lot more needs to be done as the current code is a piece of crap. Unfortunately the same holds for the current ftp code in the various BSD variants so we can't steal from them (closes: #62494). * SIGPIPE is now ignored as errors are now handled in the code (closes: #56222). -- Herbert Xu Mon, 24 Apr 2000 13:03:03 +1000 netkit-ftp (0.16-4) unstable; urgency=low * Added dynamic allocation for macro expansion (closes: #62307). -- Herbert Xu Fri, 14 Apr 2000 15:01:36 +1000 netkit-ftp (0.16-3) unstable; urgency=low * Fixed a coredump due to uninitialised parameters (closes: #61036). -- Herbert Xu Thu, 30 Mar 2000 14:24:22 +1000 netkit-ftp (0.16-2) unstable; urgency=low * Recompiled against libreadline4 (closes: #61139). -- Herbert Xu Tue, 28 Mar 2000 19:04:02 +1000 netkit-ftp (0.16-1) unstable; urgency=low * New upstream release. * Merged changes from the NMU (closes: #59682, #44778, #46132, #55652, #57906). * Added support for arbitrarily long command lines (closes: #21672). * ftp(1) is now installed as netkit-ftp and update-alternatives is now used (closes: #55610). -- Herbert Xu Thu, 23 Mar 2000 21:07:33 +1100 netkit-ftp (0.10-3.1) frozen unstable; urgency=low * Non-maintainer upload (Herbert Xu is still away, it seems). * Recompiled against libreadline4 and libncurses5, more properly closes: #44778, #46132, #55652, #57906. [ftp is Priority: standard] * Updated for Policy 3.x. Lintian clean. * Changed some bits and pieces in the build system. -- Josip Rodin Sun, 13 Feb 2000 01:20:28 +0100 netkit-ftp (0.10-3) unstable; urgency=low * Initialise transfer types upon login (fixes #20721). -- Herbert Xu Sun, 27 Jun 1999 13:38:08 +1000 netkit-ftp (0.10-2) unstable; urgency=low * Fixed buffer overrun with long lines (reported by +VipVop ). -- Herbert Xu Sun, 20 Jun 1999 12:36:31 +1000 netkit-ftp (0.10-1) unstable; urgency=low * Initial Release. * Fixed a Y2K problem with patch from Jeff Smith (fixes #39150). -- Herbert Xu Fri, 18 Jun 1999 22:39:23 +1000 debian/postinst0000644000000000000000000000040611354404035010773 0ustar #!/bin/sh # $Id: postinst,v 1.1 2000/03/23 10:27:08 herbert Exp $ set -e update-alternatives --install /usr/bin/ftp ftp /usr/bin/netkit-ftp 100 \ --slave /usr/share/man/man1/ftp.1.gz ftp.1.gz \ /usr/share/man/man1/netkit-ftp.1.gz #DEBHELPER# debian/control0000644000000000000000000000107111757223602010575 0ustar Source: netkit-ftp Section: net Priority: standard Maintainer: Alberto Gonzalez Iniesta Uploaders: Mats Erik Andersson Build-Depends: debhelper (>= 7), dpkg-dev (>= 1.15.7), libreadline-dev Standards-Version: 3.9.3 Package: ftp Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, netbase Replaces: netstd Description: classical file transfer client This is the user interface to the ARPANET standard File Transfer Protocol. The program allows a user to transfer files to and from a remote network site. debian/watch0000644000000000000000000000015411354404035010216 0ustar version=3 http://ftp.uk.linux.org/pub/linux/Networking/netkit/netkit-ftp-([.0-9]+)\.tar\.gz debian uupdate debian/patches/0000755000000000000000000000000011757217717010634 5ustar debian/patches/043_tune_non_autologin.diff0000644000000000000000000000151411576741706015762 0ustar Description: Only use implicit SYST with auto-login. Not every server, nor every ftp-proxy server, is able to reply to a SYST command before the user has logged in. . Do not execute 'dosyst()' in a situation where the user has asked for overriding auto-login. In other words, execute both of 'dologin()' and 'dosyst()', or execute none of them, depending on AUTOLOGIN. Bug-Debian: http://bugs.debian.org/611284 Forwarded: not-needed Author: Mats Erik Andersson Last-Update: 2011-05-23 --- netkit-ftp-0.17/ftp/cmds.c.debian +++ netkit-ftp-0.17/ftp/cmds.c @@ -243,9 +243,10 @@ (void) strcpy(modename, "stream"), mode = MODE_S; (void) strcpy(structname, "file"), stru = STRU_F; (void) strcpy(bytename, "8"), bytesize = 8; - if (autologin) + if (autologin) { (void) dologin(argv[1]); - dosyst(); + dosyst(); + } } } debian/patches/series0000644000000000000000000000044211757217717012051 0ustar 010_patches_in_sarge.diff 020_optional_stripping.diff 025_long_cmd_overflow.diff 030_argv_handling.diff 035_lintian_pedantic.diff 040_ipv6_ftp_c.diff 041_user_address_commands.diff 043_tune_non_autologin.diff 050_support_gnu_hurd.diff 052_no_termcap_linking.diff 060_full_offset_range.diff debian/patches/052_no_termcap_linking.diff0000644000000000000000000000772711734036711015717 0ustar Description: Remove explicit termcap linking. Present day libreadline includes all needed linking with libtinfo, so no explicit linking either with libncurses or libtermcap is needed. Author: Mats Erik Andersson Forwarded: no Last-Update: 2012-03-26 diff -Naurp netkit-ftp-0.17.debian/configure netkit-ftp-0.17/configure --- netkit-ftp-0.17.debian/configure +++ netkit-ftp-0.17/configure @@ -187,61 +187,61 @@ rm -f __conftest* ################################################## -echo -n 'Checking for ncurses... ' -cat <__conftest.c -#include -#include -#ifndef KEY_DOWN -syntax error. /* not ncurses */ -#endif -int main() { - endwin(); - return 0; -} - -EOF -if ( - $CC $CFLAGS __conftest.c -lncurses -o __conftest || exit 1 - ) >/dev/null 2>&1; then - echo 'yes' - NCURSES=1 -else - if ( - $CC $CFLAGS -I/usr/include/ncurses __conftest.c -lncurses -o __conftest || exit 1 - ) >/dev/null 2>&1; then - echo '-I/usr/include/ncurses' - CFLAGS="$CFLAGS -I/usr/include/ncurses" - NCURSES=1 - else - echo 'no' - fi -fi - -if [ x$NCURSES != x ]; then - LIBTERMCAP=-lncurses -else - echo -n 'Checking for traditional termcap... ' -cat <__conftest.c -#include -#include -int main() { - tgetent(NULL, NULL); return 0; -} - -EOF - if ( - $CC $CFLAGS __conftest.c -ltermcap -o __conftest || exit 1 - ) >/dev/null 2>&1; then - echo '-ltermcap' - LIBTERMCAP=-ltermcap - else - echo 'not found' - echo 'This package needs termcap to run.' - rm -f __conftest* - exit - fi -fi -rm -f __conftest* +#echo -n 'Checking for ncurses... ' +#cat <__conftest.c +##include +##include +##ifndef KEY_DOWN +#syntax error. /* not ncurses */ +##endif +#int main() { +# endwin(); +# return 0; +#} +# +#EOF +#if ( +# $CC $CFLAGS __conftest.c -lncurses -o __conftest || exit 1 +# ) >/dev/null 2>&1; then +# echo 'yes' +# NCURSES=1 +#else +# if ( +# $CC $CFLAGS -I/usr/include/ncurses __conftest.c -lncurses -o __conftest || exit 1 +# ) >/dev/null 2>&1; then +# echo '-I/usr/include/ncurses' +# CFLAGS="$CFLAGS -I/usr/include/ncurses" +# NCURSES=1 +# else +# echo 'no' +# fi +#fi +# +#if [ x$NCURSES != x ]; then +# LIBTERMCAP=-lncurses +#else +# echo -n 'Checking for traditional termcap... ' +#cat <__conftest.c +##include +##include +#int main() { +# tgetent(NULL, NULL); return 0; +#} +# +#EOF +# if ( +# $CC $CFLAGS __conftest.c -ltermcap -o __conftest || exit 1 +# ) >/dev/null 2>&1; then +# echo '-ltermcap' +# LIBTERMCAP=-ltermcap +# else +# echo 'not found' +# echo 'This package needs termcap to run.' +# rm -f __conftest* +# exit +# fi +#fi +#rm -f __conftest* ################################################## @@ -278,7 +278,7 @@ int main() { readline("foo"); return 0; EOF if ( - $CC $CFLAGS __conftest.c -lreadline $LIBTERMCAP -o __conftest || exit 1 + $CC $CFLAGS __conftest.c -lreadline -o __conftest || exit 1 ) >/dev/null 2>&1; then echo 'yes' USE_READLINE=1 @@ -436,7 +436,7 @@ echo 'Generating MCONFIG...' echo "LDFLAGS=$LDFLAGS" | sed 's/= */=/' echo "LIBS=$LIBS" | sed 's/= */=/' - echo "LIBTERMCAP=$LIBTERMCAP" + #echo "LIBTERMCAP=$LIBTERMCAP" echo "USE_GLIBC=$USE_GLIBC" echo "USE_READLINE=$USE_READLINE" ) > MCONFIG diff -Naurp netkit-ftp-0.17.debian/ftp/Makefile netkit-ftp-0.17/ftp/Makefile --- netkit-ftp-0.17.debian/ftp/Makefile 2012-03-26 11:50:15.000000000 +0200 +++ netkit-ftp-0.17/ftp/Makefile 2012-03-26 11:53:02.000000000 +0200 @@ -5,7 +5,7 @@ include ../MRULES ifeq ($(USE_READLINE),1) CFLAGS += -D__USE_READLINE__ -LIBS += -lreadline $(LIBTERMCAP) +LIBS += -lreadline endif ftp: cmds.o cmdtab.o domacro.o ftp.o main.o ruserpass.o debian/patches/060_full_offset_range.diff0000644000000000000000000000312311757217717015536 0ustar Description: Use full offset range. On 32-bit systems, the coding of offset values as `off_t', i.e., of 64 bit length, was incomplete. Replacing fseek() with fseeko() achieves the intended offset ranges. Bug-Debian: http://bugs.debian.org/671873 Forwarded: not-needed Author: Mats Erik Andersson, Martin Hicks Last-Update: 2012-05-23 --- netkit-ftp-0.17.debian/ftp/ftp.c +++ netkit-ftp-0.17/ftp/ftp.c @@ -720,7 +720,7 @@ sendrequest(const char *cmd, char *local if (restart_point && (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { - if (fseek(fin, restart_point, 0) < 0) { + if (fseeko(fin, restart_point, SEEK_SET) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); restart_point = 0; @@ -1095,7 +1095,7 @@ recvrequest(const char *cmd, case TYPE_I: case TYPE_L: if (restart_point && - lseek(fileno(fout), restart_point, L_SET) < 0) { + lseek(fileno(fout), restart_point, SEEK_SET) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); if (closefunc != NULL) { @@ -1149,9 +1149,10 @@ recvrequest(const char *cmd, case TYPE_A: if (restart_point) { - register int i, n, ch; + register off_t i, n; + register int ch; - if (fseek(fout, 0L, L_SET) < 0) + if (fseeko(fout, 0L, SEEK_SET) < 0) goto done; n = restart_point; for (i = 0; i++ < n;) { @@ -1160,7 +1161,7 @@ recvrequest(const char *cmd, if (ch == '\n') i++; } - if (fseek(fout, 0L, L_INCR) < 0) { + if (fseeko(fout, 0L, SEEK_CUR) < 0) { done: fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); debian/patches/040_ipv6_ftp_c.diff0000644000000000000000000003223211576737557014122 0ustar Description: Impose IPv6-capacities on ftp.c. Super structure 'struct sockaddr_storage' is replacing 'struct sockaddr_in' . For peer address strings, a first try aims at IPv4. That failing, next try is for IPv6, and ultimatively a host lookup follows as last resort. . Use a SIGALRM mechanism to decrease the default TCP handshake timeout to a value better suited for interactive use. The macro can be set externally to change the suggested FTP_CONNECT_TIMEOUT=10 . Use a command EPSV with explicit request for IPv6 address family as soon as parsing concluded that the control socket is using IPv6. . Make IP_TOS conditioned on AF_INET. Author: Mats Erik Andersson Forwarded: no Last-Update: 2011-06-17 --- netkit-ftp-0.17.debian/ftp/ftp.c +++ netkit-ftp-0.17/ftp/ftp.c @@ -71,9 +71,11 @@ int data = -1; off_t restart_point = 0; -static struct sockaddr_in hisctladdr; -static struct sockaddr_in data_addr; -static struct sockaddr_in myctladdr; +static char ipstring[INET6_ADDRSTRLEN]; /* Scribble area for resolver. */ + +static struct sockaddr_storage hisctladdr; +static struct sockaddr_storage data_addr; +static struct sockaddr_storage myctladdr; static int ptflag = 0; static int ptabflg = 0; @@ -95,40 +97,56 @@ static FILE *dataconn(const char *); static void printbytes(off_t); +#if ! defined(FTP_CONNECT_TIMEOUT) || FTP_CONNECT_TIMEOUT < 1 +# define FTP_CONNECT_TIMEOUT 10 +#endif + +static void +trivial_alarm(int sig) +{ + /* Only used to generate an EINTR error. */ + return; +} + char * hookup(char *host, int port) { - register struct hostent *hp = 0; + struct addrinfo hints, *ai = NULL, *aiptr = NULL; + struct sigaction sigact, oldsigact; + int status; volatile int s = -1; - int tos; + int tos, af_in_use; socklen_t len; static char hostnamebuf[256]; sigjmp_buf jmploc; sigjmp_buf *volatile oldtoplevel; int dupfd; + struct sockaddr_in *hisctl_sa4 = (struct sockaddr_in *) &hisctladdr; + struct sockaddr_in6 *hisctl_sa6 = (struct sockaddr_in6 *) &hisctladdr; memset(&hisctladdr, 0, sizeof(hisctladdr)); - if (inet_aton(host, &hisctladdr.sin_addr)) { - hisctladdr.sin_family = AF_INET; - strncpy(hostnamebuf, host, sizeof(hostnamebuf)); - hostnamebuf[sizeof(hostnamebuf)-1]=0; - } - else { - hp = gethostbyname(host); - if (hp == NULL) { - fprintf(stderr, "ftp: %s: ", host); - herror((char *)NULL); - code = -1; - return((char *) 0); - } - hisctladdr.sin_family = hp->h_addrtype; - if (hp->h_length > (int)sizeof(hisctladdr.sin_addr)) { - hp->h_length = sizeof(hisctladdr.sin_addr); - } - memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], hp->h_length); - (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); - hostnamebuf[sizeof(hostnamebuf)-1] = 0; + + sigact.sa_handler = trivial_alarm; + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if ( (status = getaddrinfo(host, NULL, &hints, &ai)) ) { + fprintf(stderr, "ftp: %s: %s\n", host, + gai_strerror(status)); + code = -1; + return((char *) 0); } + + aiptr = ai; + memcpy(&hisctladdr, aiptr->ai_addr, aiptr->ai_addrlen); + (void) strncpy(hostnamebuf, aiptr->ai_canonname, + sizeof(hostnamebuf)); + hostnamebuf[sizeof(hostnamebuf)-1] = 0; hostname = hostnamebuf; oldtoplevel = toplevel; @@ -141,53 +159,127 @@ toplevel = &jmploc; INTOFF; - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + s = socket(hisctladdr.ss_family, SOCK_STREAM, 0); + af_in_use = hisctladdr.ss_family; INTON; if (s < 0) { perror("ftp: socket"); + freeaddrinfo(ai); code = -1; goto out; } - hisctladdr.sin_port = port; - while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { - if (hp && hp->h_addr_list[1]) { + switch (hisctladdr.ss_family) { + case AF_INET: + hisctl_sa4->sin_port = port; + break; + case AF_INET6: + hisctl_sa6->sin6_port = port; + } + + sigaction(SIGALRM, &sigact, &oldsigact); + alarm(FTP_CONNECT_TIMEOUT); + + while (connect(s, (struct sockaddr *)&hisctladdr, + (hisctladdr.ss_family == AF_INET) + ? sizeof(struct sockaddr_in) + : sizeof(struct sockaddr_in6)) + < 0) + { + alarm(0); + sigaction(SIGALRM, &oldsigact, NULL); + if (errno == EINTR) + errno = ETIMEDOUT; + + if (aiptr && aiptr->ai_next) + { int oerrno = errno; + struct in_addr *ctladdr4 = &hisctl_sa4->sin_addr; + struct in6_addr *ctladdr6 = &hisctl_sa6->sin6_addr; - fprintf(stderr, "ftp: connect to address %s: ", - inet_ntoa(hisctladdr.sin_addr)); + switch (aiptr->ai_family) { + case AF_INET: + fprintf(stderr, "ftp: connect to address %s: ", + inet_ntop(aiptr->ai_family, + ctladdr4, + ipstring, + sizeof(ipstring))); + break; + case AF_INET6: + fprintf(stderr, "ftp: connect to address %s: ", + inet_ntop(aiptr->ai_family, + ctladdr6, + ipstring, + sizeof(ipstring))); + } errno = oerrno; perror((char *) 0); - hp->h_addr_list++; - memcpy(&hisctladdr.sin_addr, hp->h_addr_list[0], - hp->h_length); - fprintf(stdout, "Trying %s...\n", - inet_ntoa(hisctladdr.sin_addr)); + + aiptr = aiptr->ai_next; + memcpy(&hisctladdr, aiptr->ai_addr, + aiptr->ai_addrlen); + switch (hisctladdr.ss_family) { + case AF_INET: + hisctl_sa4->sin_port = port; + break; + case AF_INET6: + hisctl_sa6->sin6_port = port; + } + + switch (aiptr->ai_family) { + case AF_INET: + fprintf(stdout, "Trying %s...\n", + inet_ntop(aiptr->ai_family, + ctladdr4, + ipstring, + sizeof(ipstring))); + break; + case AF_INET6: + fprintf(stdout, "Trying %s...\n", + inet_ntop(aiptr->ai_family, + ctladdr6, + ipstring, + sizeof(ipstring))); + } INTOFF; (void) close(s); - s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + s = socket(aiptr->ai_family, SOCK_STREAM, 0); + af_in_use = aiptr->ai_family; INTON; if (s < 0) { perror("ftp: socket"); + freeaddrinfo(ai); code = -1; goto out; } + /* Try next server candidate. */ continue; } + /* No answer to any call. */ perror("ftp: connect"); + freeaddrinfo(ai); code = -1; goto bad; } + alarm(0); + sigaction(SIGALRM, &oldsigact, NULL); + len = sizeof (myctladdr); if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { perror("ftp: getsockname"); + if (ai) + freeaddrinfo(ai); code = -1; goto bad; } + if (ai) + freeaddrinfo(ai); #ifdef IP_TOS tos = IPTOS_LOWDELAY; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + if ( (af_in_use == AF_INET) && + (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(tos)) < 0) ) perror("ftp: setsockopt TOS (ignored)"); -#endif +#endif /* IP_TOS */ INTOFF; if (cin) fclose(cin); @@ -458,7 +550,7 @@ } if (dig < 4 && isdigit(c)) code = code * 10 + (c - '0'); - if (!pflag && code == 227) + if (!pflag && (code == 227 || code == 229)) pflag = 1; if (dig > 4 && pflag == 1 && isdigit(c)) pflag = 2; @@ -1198,18 +1290,21 @@ static int initconn(void) { - register char *p, *a; + register char *p = NULL, *a = NULL; int result, tmpno = 0; socklen_t len; int on = 1; int tos; u_long a1,a2,a3,a4,p1,p2; + unsigned short int port; + struct sockaddr_in *data_addr_sa4 = (struct sockaddr_in *) &data_addr; + struct sockaddr_in6 *data_addr_sa6 = (struct sockaddr_in6 *) &data_addr; if (passivemode) { INTOFF; if (data >= 0) close(data); - data = socket(AF_INET, SOCK_STREAM, 0); + data = socket(hisctladdr.ss_family, SOCK_STREAM, 0); INTON; if (data < 0) { perror("ftp: socket"); @@ -1219,32 +1314,67 @@ setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) perror("ftp: setsockopt (ignored)"); - if (command("PASV") != COMPLETE) { - printf("Passive mode refused.\n"); - return(1); - } - - /* - * What we've got at this point is a string of comma separated - * one-byte unsigned integer values, separated by commas. - * The first four are the an IP address. The fifth is the MSB - * of the port number, the sixth is the LSB. From that we'll - * prepare a sockaddr_in. - */ - - if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld", - &a1,&a2,&a3,&a4,&p1,&p2) - != 6) - { - printf("Passive mode address scan failure. Shouldn't happen!\n"); - return(1); + switch (hisctladdr.ss_family) { + case AF_INET: + if (command("PASV") != COMPLETE) { + printf("Passive mode refused.\n"); + return(1); + } + break; + case AF_INET6: + if (command("EPSV 2") != COMPLETE) { + printf("Passive mode refused.\n"); + return(1); + } } - data_addr.sin_family = AF_INET; - data_addr.sin_addr.s_addr = htonl((a1 << 24) | (a2 << 16) | - (a3 << 8) | a4); - data_addr.sin_port = htons((p1 << 8) | p2); - + if (hisctladdr.ss_family == AF_INET) { + /* + * IPv4 + * + * What we've got at this point is a string of + * comma separated one-byte unsigned integer + * values, separated by commas. The first four + * are the an IP address. The fifth is the MSB + * of the port number, the sixth is the LSB. + * From that we will prepare a sockaddr_in. + */ + + if (sscanf(pasv,"%ld,%ld,%ld,%ld,%ld,%ld", + &a1,&a2,&a3,&a4,&p1,&p2) + != 6) + { + printf("Passive mode address scan failure." + "Shouldn't happen!\n"); + return(1); + } + + data_addr.ss_family = AF_INET; + data_addr_sa4->sin_addr.s_addr = + htonl((a1 << 24) | (a2 << 16) | + (a3 << 8) | a4); + data_addr_sa4->sin_port = htons((p1 << 8) | p2); + } /* Old IPv4 command PASV */ + else { + /* EPSV for IPv6 + * + * Expected: pasv =~ "%u|" + * + * This is a shortcut based on the old code + * for getreply(), only altered to accept + * return code "229" for ESPV, in addition + * to "227" which goes with PASV. + */ + if (sscanf(pasv, "%hu", &port) != 1) { + printf("Extended passive mode address " + "scan failure. Unfortunate!\n"); + return(1); + } + data_addr = hisctladdr; + data_addr.ss_family = AF_INET6; + data_addr_sa6->sin6_port = htons(port); + } /* EPSV for IPv6 */ + if (connect(data, (struct sockaddr *) &data_addr, sizeof(data_addr))<0) { perror("ftp: connect"); @@ -1252,20 +1382,28 @@ } #ifdef IP_TOS tos = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, - sizeof(tos)) < 0) + if ( (hisctladdr.ss_family == AF_INET) && + (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(tos)) < 0) ) perror("ftp: setsockopt TOS (ignored)"); -#endif +#endif /* IP_TOS */ return(0); } noport: data_addr = myctladdr; if (sendport) - data_addr.sin_port = 0; /* let system pick one */ + /* let the system pick a port */ + switch (data_addr.ss_family) { + case AF_INET: + data_addr_sa4->sin_port = 0; + break; + case AF_INET6: + data_addr_sa6->sin6_port = 0; + } INTOFF; if (data != -1) (void) close(data); - data = socket(AF_INET, SOCK_STREAM, 0); + data = socket(data_addr.ss_family, SOCK_STREAM, 0); INTON; if (data < 0) { perror("ftp: socket"); @@ -1293,13 +1431,23 @@ if (listen(data, 1) < 0) perror("ftp: listen"); if (sendport) { - a = (char *)&data_addr.sin_addr; - p = (char *)&data_addr.sin_port; #define UC(b) (((int)b)&0xff) - result = - command("PORT %d,%d,%d,%d,%d,%d", - UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), - UC(p[0]), UC(p[1])); + switch (data_addr.ss_family) { + case AF_INET: + a = (char *)&data_addr_sa4->sin_addr; + p = (char *)&data_addr_sa4->sin_port; + result = command("PORT %d,%d,%d,%d,%d,%d", + UC(a[0]), UC(a[1]), UC(a[2]), + UC(a[3]), UC(p[0]), UC(p[1])); + break; + case AF_INET6: + result = command("EPRT |2|%s|%d|", + inet_ntop(data_addr.ss_family, + &data_addr_sa6->sin6_addr, + ipstring, + sizeof(ipstring)), + ntohs(data_addr_sa6->sin6_port)); + } if (result == ERROR && sendport == -1) { sendport = 0; tmpno = 1; @@ -1311,9 +1459,11 @@ sendport = 1; #ifdef IP_TOS on = IPTOS_THROUGHPUT; - if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + if ( (data_addr.ss_family == AF_INET) && + (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(tos)) < 0) ) perror("ftp: setsockopt TOS (ignored)"); -#endif +#endif /* IP_TOS */ return (0); bad: INTOFF; @@ -1327,7 +1477,7 @@ static FILE * dataconn(const char *lmode) { - struct sockaddr_in from; + struct sockaddr_storage from; int s, tos; socklen_t fromlen = sizeof(from); @@ -1344,9 +1494,11 @@ data = s; #ifdef IP_TOS tos = IPTOS_THROUGHPUT; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + if ( (from.ss_family == AF_INET) && + (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(tos)) < 0) ) perror("ftp: setsockopt TOS (ignored)"); -#endif +#endif /* IP_TOS */ return (fdopen(data, lmode)); } @@ -1398,8 +1550,8 @@ static struct comvars { int connect; char name[MAXHOSTNAMELEN]; - struct sockaddr_in mctl; - struct sockaddr_in hctl; + struct sockaddr_storage mctl; + struct sockaddr_storage hctl; FILE *in; FILE *out; int tpe; debian/patches/010_patches_in_sarge.diff0000644000000000000000000017632111757217717015356 0ustar Description: Source patches applied to release Sarge. Multiple patches. X-Comment: Recovered from package netkit-ftp_0.17-12.diff.gz Author: Herbert Xu Forwarded: no Last-Update: 2003-06-29 --- netkit-ftp-0.17.orig/ftp/Makefile +++ netkit-ftp-0.17/ftp/Makefile @@ -8,7 +8,7 @@ LIBS += -lreadline $(LIBTERMCAP) endif -ftp: cmds.o cmdtab.o domacro.o ftp.o glob.o main.o ruserpass.o +ftp: cmds.o cmdtab.o domacro.o ftp.o main.o ruserpass.o $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ domacro.o ftp.o glob.o main.o ruserpass.o: ftp_var.h pathnames.h --- netkit-ftp-0.17.orig/ftp/cmds.c +++ netkit-ftp-0.17/ftp/cmds.c @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -58,6 +59,7 @@ #include #include #include +#include #ifdef __USE_READLINE__ #include #include @@ -66,9 +68,7 @@ #include "ftp_var.h" #include "pathnames.h" #include "cmds.h" -#include "glob.h" - -void intr(int); +#include "main.h" extern FILE *cout; extern int data; @@ -77,17 +77,16 @@ extern char reply_string[]; static char *mname; -static sigjmp_buf jabort; -static sigjmp_buf abortprox; static char *remglob(char *argv[], int doswitch); -static int checkglob(int fd, const char *pattern); +static int checkglob(FILE *fp, const char *pattern); static char *dotrans(char *name); static char *domap(char *name); static char *globulize(char *str); static int confirm(const char *cmd, const char *file); static int getit(int argc, char *argv[], int restartit, const char *modestr); static void quote1(const char *initial, int argc, char **argv); +static void dosyst(void); /* @@ -101,13 +100,9 @@ return name; } - /* We're going to leak this memory. XXX. */ - nu = malloc(strlen(name)+3); - if (nu==NULL) { - perror("malloc"); - code = -1; - return NULL; - } + INTOFF; + nu = obstack_alloc(&mainobstack, strlen(name)+3); + INTON; strcpy(nu, "."); if (*name != '/') strcat(nu, "/"); strcat(nu, name); @@ -163,18 +158,38 @@ unsigned len = strlen(line); int ret; + size_t lynesize; + ssize_t lynelen; + char *lyne; + + /* We need obstack_unfinish() badly! */ + INTOFF; + lyne = obstack_copy(&mainobstack, line, len); + obstack_free(&lineobstack, line); + obstack_grow(&lineobstack, lyne, len); + obstack_1grow(&lineobstack, ' '); + INTON; + obstack_free(&mainobstack, lyne); - if (len >= sizeof(line) - 3) { - printf("sorry, arguments too long\n"); - intr(0); - } printf("(%s) ", prompt); - line[len++] = ' '; - if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) + lyne = NULL; + lynesize = 0; + INTOFF; + if ((lynelen = getline(&lyne, &lynesize, stdin)) == -1) { + if (lyne) + free(lyne); + suppressint = 0; intr(0); - len += strlen(&line[len]); - if (len > 0 && line[len - 1] == '\n') - line[len - 1] = '\0'; + } + if (lynelen > 0) { + obstack_grow0(&lineobstack, lyne, lyne[lynelen - 1] == '\n' ? + lynelen - 1 : lynelen); + } else { + obstack_1grow(&lineobstack, '\0'); + } + free(lyne); + INTON; + line = obstack_finish(&lineobstack); margv = makeargv(&margc, NULL); ret = margc > *pargc; *pargc = margc; @@ -218,8 +233,6 @@ } host = hookup(argv[1], port); if (host) { - int overbose; - connected = 1; /* * Set up defaults for FTP. @@ -232,62 +245,7 @@ (void) strcpy(bytename, "8"), bytesize = 8; if (autologin) (void) dologin(argv[1]); - -#if defined(__unix__) && CHAR_BIT == 8 -/* - * this ifdef is to keep someone form "porting" this to an incompatible - * system and not checking this out. This way they have to think about it. - */ - overbose = verbose; - if (debug == 0) - verbose = -1; - if (command("SYST") == COMPLETE && overbose) { - register char *cp, c = 0; - cp = index(reply_string+4, ' '); - if (cp == NULL) - cp = index(reply_string+4, '\r'); - if (cp) { - if (cp[-1] == '.') - cp--; - c = *cp; - *cp = '\0'; - } - - printf("Remote system type is %s.\n", - reply_string+4); - if (cp) - *cp = c; - } - if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { - if (proxy) - unix_proxy = 1; - else - unix_server = 1; - /* - * Set type to 0 (not specified by user), - * meaning binary by default, but don't bother - * telling server. We can use binary - * for text files unless changed by the user. - */ - type = 0; - (void) strcpy(typename, "binary"); - if (overbose) - printf("Using %s mode to transfer files.\n", - typename); - } else { - if (proxy) - unix_proxy = 0; - else - unix_server = 0; - if (overbose && - !strncmp(reply_string, "215 TOPS20", 10)) - printf( -"Remember to set tenex mode when transfering binary files from this machine.\n"); - } - verbose = overbose; -#else -#warning "Unix auto-mode code skipped" -#endif /* unix */ + dosyst(); } } @@ -513,9 +471,13 @@ mput(int argc, char *argv[]) { register int i; - void (*oldintr)(int); int ointer; char *tp; + glob_t pglob; + volatile int glob_called = 0; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; + int globerr; if (argc < 2 && !another(&argc, &argv, "local-files")) { printf("usage: %s local-files\n", argv[0]); @@ -524,8 +486,16 @@ } mname = argv[0]; mflag = 1; - oldintr = signal(SIGINT, mabort); - (void) sigsetjmp(jabort, 1); + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + if (glob_called) { + globfree(&pglob); + glob_called = 0; + } + mabort(SIGINT); + } else { + toplevel = &jmploc; + } if (proxy) { char *cp, *tp2, tmpbuf[PATH_MAX]; @@ -571,12 +541,10 @@ } } } - (void) signal(SIGINT, oldintr); - mflag = 0; - return; + goto out; } for (i = 1; i < argc; i++) { - register char **cpp, **gargs; + char **cpp; if (!doglob) { if (mflag && confirm(argv[0], argv[i])) { @@ -595,16 +563,23 @@ } continue; } - gargs = ftpglob(argv[i]); - if (globerr != NULL) { - printf("%s\n", globerr); - if (gargs) { - blkfree(gargs); - free((char *)gargs); - } + INTOFF; + globerr = glob(argv[i], GLOB_BRACE | GLOB_ERR | GLOB_NOCHECK | + GLOB_NOESCAPE | GLOB_TILDE, 0, &pglob); + switch (globerr) { + case GLOB_NOSPACE: + errno = ENOMEM; + goto err; + case GLOB_ABORTED: + globfree(&pglob); +err: + INTON; + puts(strerror(errno)); continue; } - for (cpp = gargs; cpp && *cpp != NULL; cpp++) { + glob_called = 1; + INTON; + for (cpp = pglob.gl_pathv; *cpp; cpp++) { if (mflag && confirm(argv[0], *cpp)) { tp = (ntflag) ? dotrans(*cpp) : *cpp; tp = (mapflag) ? domap(tp) : tp; @@ -620,12 +595,13 @@ } } } - if (gargs != NULL) { - blkfree(gargs); - free((char *)gargs); - } + INTOFF; + globfree(&pglob); + glob_called = 0; + INTON; } - (void) signal(SIGINT, oldintr); +out: + toplevel = oldtoplevel; mflag = 0; } @@ -657,10 +633,6 @@ * local names. */ argv[2] = pipeprotect(argv[1]); - if (!argv[2]) { - code = -1; - return 0; - } loc++; } if (argc < 2 && !another(&argc, &argv, "remote-file")) @@ -785,12 +757,11 @@ interactive = 1; if (confirm("Continue with", mname)) { interactive = ointer; - siglongjmp(jabort,0); + return; } interactive = ointer; } mflag = 0; - siglongjmp(jabort,0); } /* @@ -799,9 +770,10 @@ void mget(int argc, char **argv) { - void (*oldintr)(int); int ointer; char *cp, *tp, *tp2, tmpbuf[PATH_MAX]; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (argc < 2 && !another(&argc, &argv, "remote-files")) { printf("usage: %s remote-files\n", argv[0]); @@ -810,8 +782,12 @@ } mname = argv[0]; mflag = 1; - oldintr = signal(SIGINT,mabort); - (void) sigsetjmp(jabort, 1); + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + mabort(SIGINT); + } else { + toplevel = &jmploc; + } while ((cp = remglob(argv,proxy)) != NULL) { if (*cp == '\0') { mflag = 0; @@ -847,14 +823,8 @@ /* Prepend ./ to "-" or "!*" or leading "/" */ tp = pipeprotect(tp); - if (tp == NULL) { - /* hmm... how best to handle this? */ - mflag = 0; - } - else { - recvrequest("RETR", tp, cp, "w", - tp != cp || !interactive); - } + recvrequest("RETR", tp, cp, "w", + tp != cp || !interactive); if (!mflag && fromatty) { ointer = interactive; interactive = 1; @@ -865,14 +835,13 @@ } } } - (void) signal(SIGINT,oldintr); + toplevel = oldtoplevel; mflag = 0; } char * remglob(char *argv[], int doswitch) { - char temp[16]; static char buf[PATH_MAX]; static FILE *ftemp = NULL; static char **args; @@ -885,8 +854,10 @@ } else { if (ftemp) { + INTOFF; (void) fclose(ftemp); ftemp = NULL; + INTON; } } return(NULL); @@ -899,34 +870,88 @@ return (cp); } if (ftemp == NULL) { - int oldumask, fd; + char temp[16] = ""; +#if !defined(__GLIBC__) || !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)) + int oldumask; +#endif + volatile int fd = -1; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; + (void) strcpy(temp, _PATH_TMP); + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 0)) { + if (fd >= 0) { + unlink(temp); + close(fd); + } + toplevel = oldtoplevel; + siglongjmp(*toplevel, 1); + } + toplevel = &jmploc; + /* libc 5.2.18 creates with mode 0666, which is dumb */ + INTOFF; +#if !defined(__GLIBC__) || !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)) oldumask = umask(077); +#endif fd = mkstemp(temp); +#if !defined(__GLIBC__) || !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 0)) umask(oldumask); +#endif + INTON; if (fd<0) { + toplevel = oldtoplevel; printf("Error creating temporary file, oops\n"); return NULL; } - + oldverbose = verbose, verbose = 0; oldhash = hash, hash = 0; if (doswitch) { pswitch(!proxy); } while (*++argv != NULL) { - int dupfd = dup(fd); + int dupfd; recvrequest ("NLST", temp, *argv, "a", 0); - if (!checkglob(dupfd, *argv)) { - badglob = 1; + + INTOFF; + if ((dupfd = dup(fd)) < 0) { + INTON; + perror("remglob: dup"); +duperr: + INTOFF; + unlink(temp); + close(fd); + fd = -1; + INTON; + toplevel = oldtoplevel; + return NULL; + } + if ((ftemp = fdopen(dupfd, "r")) == NULL) { + int olderrno = errno; + close(dupfd); + INTON; + errno = olderrno; + perror("remglob: fdopen"); + goto duperr; + } + INTON; + + badglob = !checkglob(ftemp, *argv); + + INTOFF; + fclose(ftemp); + ftemp = NULL; + INTON; + + if (badglob) { break; } } - unlink(temp); if (doswitch) { pswitch(!proxy); @@ -934,18 +959,27 @@ verbose = oldverbose; hash = oldhash; if (badglob) { printf("Refusing to handle insecure file list\n"); - close(fd); - return NULL; + goto duperr; } + + INTOFF; + unlink(temp); ftemp = fdopen(fd, "r"); + fd = -1; + INTON; + toplevel = oldtoplevel; + if (ftemp == NULL) { printf("fdopen failed, oops\n"); return NULL; } + rewind(ftemp); } if (fgets(buf, sizeof (buf), ftemp) == NULL) { + INTOFF; (void) fclose(ftemp), ftemp = NULL; + INTON; return (NULL); } if ((cp = index(buf, '\n')) != NULL) @@ -993,12 +1027,11 @@ * --okir */ static int -checkglob(int fd, const char *pattern) +checkglob(FILE *fp, const char *pattern) { const char *sp; char buffer[MAXPATHLEN], dotdot[MAXPATHLEN]; int okay = 1, nrslash, initial, nr; - FILE *fp; /* Find slashes in glob pattern, and verify whether component * matches `..' @@ -1014,7 +1047,6 @@ dotdot[nrslash++] = isdotdotglob(sp); } - fp = fdopen(fd, "r"); while (okay && fgets(buffer, sizeof(buffer), fp) != NULL) { char *sp; @@ -1043,7 +1075,6 @@ printf("Filename provided by server " "doesn't match pattern `%s': %s\n", pattern, buffer); - fclose(fp); return okay; } @@ -1083,6 +1114,7 @@ printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), onoff(runique)); printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); + printf("Quote control characters: %s\n", onoff(qcflag)); if (ntflag) { printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); } @@ -1316,9 +1348,10 @@ void mdelete(int argc, char *argv[]) { - void (*oldintr)(int); int ointer; char *cp; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (argc < 2 && !another(&argc, &argv, "remote-files")) { printf("usage: %s remote-files\n", argv[0]); @@ -1327,8 +1360,12 @@ } mname = argv[0]; mflag = 1; - oldintr = signal(SIGINT, mabort); - (void) sigsetjmp(jabort, 1); + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + mabort(SIGINT); + } else { + toplevel = &jmploc; + } while ((cp = remglob(argv,0)) != NULL) { if (*cp == '\0') { mflag = 0; @@ -1346,7 +1383,7 @@ } } } - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; mflag = 0; } @@ -1390,16 +1427,15 @@ code = -1; return; } + cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; - if (strcmp(argv[2], "-") && (argv[2] = globulize(argv[2]))==NULL) { - code = -1; - return; - } - if (strcmp(argv[2], "-") && *argv[2] != '|') - if ((argv[2] = globulize(argv[2]))==NULL || + if (strcmp(argv[2], "-") && *argv[2] != '|') { + argv[2] = globulize(argv[2]); + if (argv[2] == NULL || !confirm("output to local-file:", argv[2])) { code = -1; return; + } } recvrequest(cmd, argv[2], argv[1], "w", 0); } @@ -1411,11 +1447,12 @@ void mls(int argc, char *argv[]) { - void (*oldintr)(int); int ointer, i; const char *volatile cmd; char *volatile dest; const char *modestr; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (argc < 2 && !another(&argc, &argv, "remote-files")) goto usage; @@ -1425,23 +1462,30 @@ code = -1; return; } + dest = argv[argc - 1]; argv[argc - 1] = NULL; - if (strcmp(dest, "-") && *dest != '|') - if ((dest = globulize(dest))==NULL || - !confirm("output to local-file:", dest)) { + + if (strcmp(dest, "-") && *dest != '|') { + dest = globulize(dest); + if (dest == NULL || !confirm("output to local-file:", dest)) { code = -1; return; + } } cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; mname = argv[0]; mflag = 1; - oldintr = signal(SIGINT, mabort); /* * This just plain seems wrong. */ - (void) sigsetjmp(jabort, 1); + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + mabort(SIGINT); + } else { + toplevel = &jmploc; + } for (i = 1; mflag && i < argc-1; ++i) { modestr = (i == 1) ? "w" : "a"; @@ -1455,7 +1499,7 @@ interactive = ointer; } } - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; mflag = 0; } @@ -1555,6 +1599,7 @@ if (!aflag && argc == 4) { (void) command("ACCT %s", argv[3]); } + dosyst(); } /* @@ -1651,19 +1696,28 @@ static void quote1(const char *initial, int argc, char **argv) { - register int i, len; - char buf[BUFSIZ]; /* must be >= sizeof(line) */ + register int i; + char *buf; - (void) strcpy(buf, initial); + INTOFF; + obstack_grow(&mainobstack, initial, strlen(initial)); if (argc > 1) { - len = strlen(buf); - len += strlen(strcpy(&buf[len], argv[1])); + obstack_grow(&mainobstack, argv[1], strlen(argv[1])); for (i = 2; i < argc; i++) { - buf[len++] = ' '; - len += strlen(strcpy(&buf[len], argv[i])); + obstack_1grow(&mainobstack, ' '); + obstack_grow(&mainobstack, argv[i], strlen(argv[i])); } } - if (command("%s", buf) == PRELIM) { + INTON; + + obstack_1grow(&mainobstack, '\0'); + buf = obstack_finish(&mainobstack); + i = command("%s", buf); + INTOFF; + obstack_free(&mainobstack, buf); + INTON; + + if (i == PRELIM) { while (getreply(0) == PRELIM); } } @@ -1742,11 +1796,18 @@ return; (void) command("QUIT"); if (cout) { + INTOFF; (void) fclose(cout); + cout = NULL; + INTON; + } + if (data >= 0) { + INTOFF; + close(data); + data = -1; + INTON; } - cout = NULL; connected = 0; - data = -1; if (!proxy) { macnum = 0; } @@ -1764,10 +1825,16 @@ if (fromatty && !rl_inhibit) { char *lineread; snprintf(lyne, BUFSIZ, "%s %s? ", cmd, file); + /* XXX readline memory leak */ lineread = readline(lyne); - if (!lineread) return 0; - strcpy(lyne, lineread); + if (!lineread) { + return 0; + } + INTOFF; + lyne[0] = lineread[0]; free(lineread); + INTON; + lyne[1] = 0; } else { #endif @@ -1800,28 +1867,28 @@ char * globulize(char *cpp) { - char **globbed; - char *rv = cpp; + char *rv; + glob_t pglob; if (!doglob) return cpp; - globbed = ftpglob(cpp); - if (globerr != NULL) { - printf("%s: %s\n", cpp, globerr); - if (globbed) { - blkfree(globbed); - free(globbed); - } + INTOFF; + switch(glob(cpp, GLOB_BRACE | GLOB_ERR | GLOB_NOCHECK | + GLOB_NOESCAPE | GLOB_TILDE, 0, &pglob)) { + case GLOB_NOSPACE: + errno = ENOMEM; + goto err; + case GLOB_ABORTED: + globfree(&pglob); +err: + INTON; + puts(strerror(errno)); return NULL; } - if (globbed) { - rv = globbed[0]; - /* don't waste too much memory */ - if (globbed[0]) { - blkfree(globbed+1); - } - free(globbed); - } + rv = pglob.gl_pathv[0]; + rv = obstack_copy0(&mainobstack, rv, strlen(rv)); + globfree(&pglob); + INTON; return rv; } @@ -1862,14 +1929,14 @@ proxflag = 0; } pswitch(0); - siglongjmp(abortprox,1); } void doproxy(int argc, char *argv[]) { register struct cmd *c; - void (*oldintr)(int); + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (argc < 2 && !another(&argc, &argv, "command")) { printf("usage: %s command\n", argv[0]); @@ -1895,17 +1962,20 @@ code = -1; return; } - if (sigsetjmp(abortprox, 1)) { + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + proxabort(SIGINT); + toplevel = oldtoplevel; code = -1; return; } - oldintr = signal(SIGINT, proxabort); + toplevel = &jmploc; pswitch(1); if (c->c_conn && !connected) { printf("Not connected\n"); (void) fflush(stdout); pswitch(0); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } @@ -1921,7 +1991,7 @@ proxflag = 0; } pswitch(0); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; } void @@ -1941,6 +2011,14 @@ } void +setqc(void) +{ + qcflag = !qcflag; + printf("Quote control characters %s.\n", onoff(qcflag)); + code = qcflag; +} + +void setntrans(int argc, char *argv[]) { if (argc == 1) { @@ -2225,8 +2303,8 @@ if (argc != 2) printf("restart: offset not specified\n"); else { - restart_point = atol(argv[1]); - printf("restarting at %ld. %s\n", restart_point, + restart_point = atoll(argv[1]); + printf("restarting at %jd. %s\n", (intmax_t) restart_point, "execute get, put or append to initiate transfer"); } } @@ -2374,3 +2452,69 @@ argv[2], argv[1]); } } + +/* + * initialise file types etc + */ +static void +dosyst() +{ +#if defined(__unix__) && CHAR_BIT == 8 +/* + * this ifdef is to keep someone form "porting" this to an incompatible + * system and not checking this out. This way they have to think about it. + */ + + int overbose; + + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("SYST") == COMPLETE && overbose) { + register char *cp, c = 0; + cp = index(reply_string+4, ' '); + if (cp == NULL) + cp = index(reply_string+4, '\r'); + if (cp) { + if (cp[-1] == '.') + cp--; + c = *cp; + *cp = '\0'; + } + + printf("Remote system type is %s.\n", + reply_string+4); + if (cp) + *cp = c; + } + if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { + if (proxy) + unix_proxy = 1; + else + unix_server = 1; + /* + * Set type to 0 (not specified by user), + * meaning binary by default, but don't bother + * telling server. We can use binary + * for text files unless changed by the user. + */ + type = 0; + (void) strcpy(typename, "binary"); + if (overbose) + printf("Using %s mode to transfer files.\n", + typename); + } else { + if (proxy) + unix_proxy = 0; + else + unix_server = 0; + if (overbose && + !strncmp(reply_string, "215 TOPS20", 10)) + printf( +"Remember to set tenex mode when transfering binary files from this machine.\n"); + } + verbose = overbose; +#else +#warning "Unix auto-mode code skipped" +#endif /* unix */ +} --- netkit-ftp-0.17.orig/ftp/cmds.h +++ netkit-ftp-0.17/ftp/cmds.h @@ -42,6 +42,7 @@ void makedir(int argc, char *argv[]); void removedir(int argc, char *argv[]); void setcr(void); +void setqc(void); void account(int argc, char *argv[]); void doproxy(int argc, char *argv[]); void reset(void); --- netkit-ftp-0.17.orig/ftp/cmdtab.c +++ netkit-ftp-0.17/ftp/cmdtab.c @@ -56,6 +56,7 @@ const char chmodhelp[] = "change file permissions of remote file"; const char connecthelp[] = "connect to remote ftp"; const char crhelp[] = "toggle carriage return stripping on ascii gets"; +const char qchelp[] = "print ? in place of control characters on stdout"; const char deletehelp[] = "delete remote file"; const char debughelp[] = "toggle/set debugging mode"; const char dirhelp[] = "list contents of remote directory"; @@ -160,6 +161,7 @@ { "prompt", prompthelp, 0, 0, 0, NULL, setprompt, NULL }, { "passive", passivehelp, 0, 0, 0, NULL, setpassive, NULL }, { "proxy", proxyhelp, 0, 0, 1, doproxy, NULL, NULL }, + { "qc", qchelp, 0, 0, 0, NULL, setqc, NULL }, { "sendport", porthelp, 0, 0, 0, NULL, setport, NULL }, { "put", sendhelp, 1, 1, 1, put, NULL, NULL }, { "pwd", pwdhelp, 0, 1, 1, NULL, pwd, NULL }, --- netkit-ftp-0.17.orig/ftp/domacro.c +++ netkit-ftp-0.17/ftp/domacro.c @@ -40,9 +40,21 @@ #include #include #include +#include #include #include "ftp_var.h" +#include "main.h" + +static char *append(char *p, const char *s) { + size_t slen = strlen(s); + + INTOFF; + obstack_blank(&lineobstack, slen); + INTON; + memcpy(p, s, slen); + return p + slen; +} void domacro(int argc, char *argv[]) @@ -53,8 +65,9 @@ register int i, j; register char *cp1, *cp2; int count = 2, loopflg = 0; - char line2[200]; + char *line2; struct cmd *c; + size_t len; if (argc < 2 && !another(&argc, &argv, "macro name")) { printf("Usage: %s macro_name.\n", argv[0]); @@ -71,14 +84,18 @@ code = -1; return; } - (void) strcpy(line2, line); + line2 = line; TOP: cp1 = macros[i].mac_start; while (cp1 != macros[i].mac_end) { while (isspace(*cp1)) { cp1++; } - cp2 = line; + len = strlen(cp1) + 1; + INTOFF; + obstack_blank(&lineobstack, len); + INTON; + cp2 = obstack_base(&lineobstack); while (*cp1 != '\0') { switch(*cp1) { case '\\': @@ -92,8 +109,7 @@ } cp1--; if (argc - 2 >= j) { - (void) strcpy(cp2, argv[j+1]); - cp2 += strlen(argv[j+1]); + cp2 = append(cp2, argv[j+1]); } break; } @@ -101,8 +117,7 @@ loopflg = 1; cp1++; if (count < argc) { - (void) strcpy(cp2, argv[count]); - cp2 += strlen(argv[count]); + cp2 = append(cp2, argv[count]); } break; } @@ -116,6 +131,7 @@ } } *cp2 = '\0'; + line = obstack_finish(&lineobstack); margv = makeargv(&margc, &marg); c = getcmd(margv[0]); if (c == (struct cmd *)-1) { @@ -141,11 +157,19 @@ if (bell && c->c_bell) { (void) putchar('\007'); } - (void) strcpy(line, line2); + INTOFF; + obstack_free(&lineobstack, line); + INTON; + line = line2; margv = makeargv(&margc, &marg); argc = margc; argv = margv; } + if (line != line2) { + INTOFF; + obstack_free(&lineobstack, line); + INTON; + } if (cp1 != macros[i].mac_end) { cp1++; } @@ -153,4 +177,5 @@ if (loopflg && ++count < argc) { goto TOP; } + line = line2; } --- netkit-ftp-0.17.orig/ftp/ftp.1 +++ netkit-ftp-0.17/ftp/ftp.1 @@ -43,10 +43,10 @@ .Sh SYNOPSIS .Nm ftp .Op Fl pinegvd -.Op Ar host +.Op Ar host Op Ar port .Nm pftp .Op Fl inegvd -.Op Ar host +.Op Ar host Op Ar port .Sh DESCRIPTION .Nm Ftp is the user interface to the @@ -99,7 +99,7 @@ Enables debugging. .El .Pp -The client host with which +The client host and an optional port number with which .Nm ftp is to communicate may be specified on the command line. If this is done, @@ -218,6 +218,13 @@ distinguished from a record delimiter only when .Ic \&cr is off. +.It Ic qc +Toggle the printing of control characters in the output of +.Tn ASCII +type commands. When this is turned on, control characters +are replaced with a question mark if the output file is the +standard output. This is the default when the standard +output is a tty. .It Ic delete Ar remote-file Delete the file .Ar remote-file @@ -698,6 +705,9 @@ .Ar remote-file and the transfer is continued from the apparent point of failure. +If +.Ar local-file +does not exist ftp won't fetch the file. This command is useful when transferring very large files over networks that are prone to dropping connections. @@ -1030,6 +1040,7 @@ .El .Sh SEE ALSO .Xr ftpd 8 , +.Xr netrc 5 , RFC 959 .Sh HISTORY The --- netkit-ftp-0.17.orig/ftp/ftp.c +++ netkit-ftp-0.17/ftp/ftp.c @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -59,9 +60,11 @@ #include #include #include +#include #include "ftp_var.h" #include "cmds.h" +#include "main.h" #include "../version.h" @@ -72,11 +75,7 @@ static struct sockaddr_in data_addr; static struct sockaddr_in myctladdr; static int ptflag = 0; -static sigjmp_buf recvabort; -static sigjmp_buf sendabort; -static sigjmp_buf ptabort; static int ptabflg = 0; -static int abrtflag = 0; void lostpeer(int); extern int connected; @@ -84,7 +83,7 @@ static char *gunique(char *); static void proxtrans(const char *cmd, char *local, char *remote); static int initconn(void); -static void ptransfer(const char *direction, long bytes, +static void ptransfer(const char *direction, off_t bytes, const struct timeval *t0, const struct timeval *t1); static void tvsub(struct timeval *tdiff, @@ -94,14 +93,19 @@ FILE *cin, *cout; static FILE *dataconn(const char *); +static void printbytes(off_t); char * hookup(char *host, int port) { register struct hostent *hp = 0; - int s, tos; + volatile int s = -1; + int tos; socklen_t len; static char hostnamebuf[256]; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; + int dupfd; memset(&hisctladdr, 0, sizeof(hisctladdr)); if (inet_aton(host, &hisctladdr.sin_addr)) { @@ -126,11 +130,23 @@ hostnamebuf[sizeof(hostnamebuf)-1] = 0; } hostname = hostnamebuf; + + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 0)) { + if (s >= 0) + close(s); + toplevel = oldtoplevel; + siglongjmp(*toplevel, 1); + } + toplevel = &jmploc; + + INTOFF; s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + INTON; if (s < 0) { perror("ftp: socket"); code = -1; - return (0); + goto out; } hisctladdr.sin_port = port; while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { @@ -146,12 +162,14 @@ hp->h_length); fprintf(stdout, "Trying %s...\n", inet_ntoa(hisctladdr.sin_addr)); + INTOFF; (void) close(s); s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + INTON; if (s < 0) { perror("ftp: socket"); code = -1; - return (0); + goto out; } continue; } @@ -170,26 +188,49 @@ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) perror("ftp: setsockopt TOS (ignored)"); #endif + INTOFF; + if (cin) + fclose(cin); + if (cout) + fclose(cout); cin = fdopen(s, "r"); - cout = fdopen(s, "w"); + if (cin == NULL) + close(s); + dupfd = dup(s); + cout = fdopen(dup(s), "w"); + if (cout == NULL && dupfd >= 0) + close(dupfd); + s = -1; + toplevel = oldtoplevel; + INTON; if (cin == NULL || cout == NULL) { fprintf(stderr, "ftp: fdopen failed.\n"); - if (cin) + if (cin) { + INTOFF; (void) fclose(cin); - if (cout) + cin = NULL; + INTON; + } + if (cout) { + INTOFF; (void) fclose(cout); + cout = NULL; + INTON; + } code = -1; - goto bad; + goto out; } if (verbose) printf("Connected to %s.\n", hostname); if (getreply(0) > 2) { /* read startup message from server */ - if (cin) - (void) fclose(cin); - if (cout) - (void) fclose(cout); + INTOFF; + fclose(cin); + fclose(cout); + cin = NULL; + cout = NULL; + INTON; code = -1; - goto bad; + goto out; } #ifdef SO_OOBINLINE { @@ -204,7 +245,12 @@ return (hostname); bad: + INTOFF; (void) close(s); + s = -1; + INTON; +out: + toplevel = oldtoplevel; return ((char *)0); } @@ -216,10 +262,13 @@ int n, aflag = 0; luser = pass = zacct = 0; + INTOFF; if (xruserpass(host, &luser, &pass, &zacct) < 0) { + INTON; code = -1; return(0); } + INTON; while (luser == NULL) { char *myname = getlogin(); @@ -233,11 +282,13 @@ printf("Name (%s:%s): ", host, myname); else printf("Name (%s): ", host); - if (fgets(tmp, sizeof(tmp) - 1, stdin)==NULL) { + if (fgets(tmp, sizeof(tmp), stdin)==NULL) { fprintf(stderr, "\nLogin failed.\n"); return 0; } - tmp[strlen(tmp) - 1] = '\0'; + n = strlen(tmp); + if (tmp[n - 1] == '\n') + tmp[n - 1] = 0; if (*tmp == '\0') luser = myname; else @@ -269,42 +320,35 @@ if (!strcmp("init", macros[n].mac_name)) { int margc; char **margv; - strcpy(line, "$init"); + char *oldline = line; + INTOFF; + line = obstack_copy(&lineobstack, "$init", 6); + INTON; margv = makeargv(&margc, NULL); domacro(margc, margv); + INTOFF; + obstack_free(&lineobstack, line); + INTON; + line = oldline; break; } } return (1); } - -static void -cmdabort(int ignore) -{ - (void)ignore; - - printf("\n"); - fflush(stdout); - abrtflag++; - if (ptflag) siglongjmp(ptabort,1); -} - int command(const char *fmt, ...) { va_list ap; int r; - void (*oldintr)(int); - abrtflag = 0; if (debug) { printf("---> "); va_start(ap, fmt); if (strncmp("PASS ", fmt, 5) == 0) printf("PASS XXXX"); else - vfprintf(stdout, fmt, ap); + vprintf(fmt, ap); va_end(ap); printf("\n"); (void) fflush(stdout); @@ -314,18 +358,28 @@ code = -1; return (0); } - oldintr = signal(SIGINT, cmdabort); + INTOFF; + intrnewline++; va_start(ap, fmt); vfprintf(cout, fmt, ap); va_end(ap); - fprintf(cout, "\r\n"); - (void) fflush(cout); + fputs("\r\n", cout); + if (fflush(cout) == EOF) + goto outerr; cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); - if (abrtflag && oldintr != SIG_IGN) - (*oldintr)(SIGINT); - (void) signal(SIGINT, oldintr); + intrnewline--; + INTON; return(r); +outerr: + lostpeer(0); + INTON; + if (verbose) { + printf("421 Service not available, remote server has closed connection\n"); + fflush(stdout); + } + code = 421; + return 4; } char reply_string[BUFSIZ]; /* last line of previous reply */ @@ -339,12 +393,16 @@ register int dig; register char *cp; int originalcode = 0, continuation = 0; - void (*oldintr)(int); int pflag = 0; size_t px = 0; size_t psize = sizeof(pasv); - oldintr = signal(SIGINT, cmdabort); + if (!cin || !cout) { + cpend = 0; + return 4; + } + INTOFF; + intrnewline++; for (;;) { dig = n = code = 0; cp = reply_string; @@ -353,15 +411,19 @@ switch (c = getc(cin)) { case WILL: case WONT: - c = getc(cin); + if ((c = getc(cin)) == EOF) + goto goteof; fprintf(cout, "%c%c%c", IAC, DONT, c); - (void) fflush(cout); + if (fflush(cout) == EOF) + goto goteof; break; case DO: case DONT: - c = getc(cin); + if ((c = getc(cin)) == EOF) + goto goteof; fprintf(cout, "%c%c%c", IAC, WONT, c); - (void) fflush(cout); + if (fflush(cout) == EOF) + goto goteof; break; default: break; @@ -371,11 +433,15 @@ dig++; if (c == EOF) { if (expecteof) { - (void) signal(SIGINT,oldintr); + intrnewline--; + INTON; code = 221; return (0); } +goteof: lostpeer(0); + intrnewline--; + INTON; if (verbose) { printf("421 Service not available, remote server has closed connection\n"); (void) fflush(stdout); @@ -427,11 +493,13 @@ *cp = '\0'; if (n != '1') cpend = 0; - (void) signal(SIGINT,oldintr); - if (code == 421 || originalcode == 421) + intrnewline--; + INTON; + if (code == 421 || originalcode == 421) { + INTOFF; lostpeer(0); - if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) - (*oldintr)(SIGINT); + INTON; + } return (n - '0'); } } @@ -452,10 +520,8 @@ (void)ignore; mflag = 0; - abrtflag = 0; printf("\nsend aborted\nwaiting for remote to finish abort\n"); (void) fflush(stdout); - siglongjmp(sendabort, 1); } #define HASHBYTES 1024 @@ -466,13 +532,13 @@ struct stat st; struct timeval start, stop; register int c, d; - FILE *volatile fin, *volatile dout = 0; + FILE *volatile fin = 0, *volatile dout = 0; int (*volatile closefunc)(FILE *); - void (*volatile oldintr)(int); - void (*volatile oldintp)(int); - volatile long bytes = 0, hashbytes = HASHBYTES; + volatile off_t bytes = 0, hashbytes = HASHBYTES; char buf[BUFSIZ], *bufp; const char *volatile lmode; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (verbose && printnames) { if (local && *local != '-') @@ -487,84 +553,104 @@ if (curtype != type) changetype(type, 0); closefunc = NULL; - oldintr = NULL; - oldintp = NULL; lmode = "w"; - if (sigsetjmp(sendabort, 1)) { + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + abortsend(SIGINT); while (cpend) { (void) getreply(0); } if (data >= 0) { + INTOFF; (void) close(data); data = -1; + INTON; } - if (oldintr) - (void) signal(SIGINT,oldintr); - if (oldintp) - (void) signal(SIGPIPE,oldintp); + if (fin != NULL && closefunc != NULL) + (*closefunc)(fin); + toplevel = oldtoplevel; code = -1; return; } - oldintr = signal(SIGINT, abortsend); + toplevel = &jmploc; if (strcmp(local, "-") == 0) fin = stdin; else if (*local == '|') { - oldintp = signal(SIGPIPE,SIG_IGN); + closefunc = pclose; + INTOFF; fin = popen(local + 1, "r"); + INTON; if (fin == NULL) { perror(local + 1); - (void) signal(SIGINT, oldintr); - (void) signal(SIGPIPE, oldintp); + toplevel = oldtoplevel; code = -1; return; } - closefunc = pclose; } else { + closefunc = fclose; + INTOFF; fin = fopen(local, "r"); + INTON; if (fin == NULL) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } - closefunc = fclose; if (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG) { fprintf(stdout, "%s: not a plain file.\n", local); - (void) signal(SIGINT, oldintr); + INTOFF; fclose(fin); + fin = NULL; + INTON; + toplevel = oldtoplevel; code = -1; return; } } if (initconn()) { - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); code = -1; - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; return; } - if (sigsetjmp(sendabort, 1)) + if (sigsetjmp(jmploc, 1)) { + abortsend(SIGINT); goto abort; + } if (restart_point && (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { - if (fseek(fin, (long) restart_point, 0) < 0) { + if (fseek(fin, restart_point, 0) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); restart_point = 0; - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; return; } - if (command("REST %ld", (long) restart_point) + if (command("REST %jd", (intmax_t) restart_point) != CONTINUE) { restart_point = 0; - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; return; } restart_point = 0; @@ -572,27 +658,32 @@ } if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; return; } } else if (command("%s", cmd) != PRELIM) { - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; return; } + INTOFF; dout = dataconn(lmode); + INTON; if (dout == NULL) goto abort; (void) gettimeofday(&start, (struct timezone *)0); - oldintp = signal(SIGPIPE, SIG_IGN); switch (curtype) { case TYPE_I: @@ -601,8 +692,10 @@ while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; for (bufp = buf; c > 0; c -= d, bufp += d) - if ((d = write(fileno(dout), bufp, c)) <= 0) + if ((d = write(fileno(dout), bufp, c)) <= 0) { + perror("netout"); break; + } if (hash) { while (bytes >= hashbytes) { (void) putchar('#'); @@ -611,11 +704,12 @@ (void) fflush(stdout); } if (tick && (bytes >= hashbytes)) { - printf("\rBytes transferred: %ld", bytes); - (void) fflush(stdout); + printbytes(bytes); while (bytes >= hashbytes) hashbytes += TICKBYTES; } + if (d <= 0) + break; } if (hash && (bytes > 0)) { if (bytes < HASHBYTES) @@ -624,17 +718,13 @@ (void) fflush(stdout); } if (tick) { - (void) printf("\rBytes transferred: %ld\n", bytes); - (void) fflush(stdout); + printbytes(bytes); } if (c < 0) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - if (d < 0) { - if (errno != EPIPE) - perror("netout"); + if (d <= 0) bytes = -1; - } break; case TYPE_A: @@ -646,18 +736,20 @@ hashbytes += HASHBYTES; } if (tick && (bytes >= hashbytes)) { - (void) printf("\rBytes transferred: %ld", - bytes); - (void) fflush(stdout); + printbytes(bytes); while (bytes >= hashbytes) hashbytes += TICKBYTES; } - if (ferror(dout)) + if (putc('\r', dout) == EOF) { + perror("netout"); break; - (void) putc('\r', dout); + } bytes++; } - (void) putc(c, dout); + if (putc(c, dout) == EOF) { + perror("netout"); + break; + } bytes++; /* if (c == '\r') { */ /* (void) putc('\0', dout); (* this violates rfc */ @@ -671,53 +763,63 @@ (void) fflush(stdout); } if (tick) { - (void) printf("\rBytes transferred: %ld\n", bytes); - (void) fflush(stdout); + printbytes(bytes); } if (ferror(fin)) fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - if (ferror(dout)) { - if (errno != EPIPE) - perror("netout"); + if (ferror(dout)) bytes = -1; - } break; } (void) gettimeofday(&stop, (struct timezone *)0); - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + INTOFF; (void) fclose(dout); + dout = NULL; /* closes data as well, so discard it */ data = -1; + INTON; (void) getreply(0); - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); + toplevel = oldtoplevel; if (bytes > 0) ptransfer("sent", bytes, &start, &stop); return; abort: (void) gettimeofday(&stop, (struct timezone *)0); - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); if (!cpend) { code = -1; + toplevel = oldtoplevel; return; } if (dout) { + INTOFF; + if (data == fileno(dout)) + data = -1; (void) fclose(dout); + dout = NULL; + INTON; } if (data >= 0) { - /* if it just got closed with dout, again won't hurt */ + INTOFF; (void) close(data); data = -1; + INTON; } (void) getreply(0); code = -1; - if (closefunc != NULL && fin != NULL) + if (closefunc != NULL && fin != NULL) { + INTOFF; (*closefunc)(fin); + fin = NULL; + INTON; + } + toplevel = oldtoplevel; if (bytes > 0) ptransfer("sent", bytes, &start, &stop); } @@ -728,10 +830,8 @@ (void)ignore; mflag = 0; - abrtflag = 0; printf("\nreceive aborted\nwaiting for remote to finish abort\n"); (void) fflush(stdout); - siglongjmp(recvabort, 1); } void @@ -739,17 +839,18 @@ char *volatile local, char *remote, const char *lmode, int printnames) { - FILE *volatile fout, *volatile din = 0; + FILE *volatile fout = 0, *volatile din = 0; int (*volatile closefunc)(FILE *); - void (*volatile oldintp)(int); - void (*volatile oldintr)(int); volatile int is_retr, tcrflag, bare_lfs = 0; - static unsigned bufsize; - static char *buf; - volatile long bytes = 0, hashbytes = HASHBYTES; + int tqcflag = 0; + unsigned bufsize; + char *buf; + volatile off_t bytes = 0, hashbytes = HASHBYTES; register int c, d; struct timeval start, stop; struct stat st; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; is_retr = strcmp(cmd, "RETR") == 0; if (is_retr && verbose && printnames) { @@ -763,23 +864,24 @@ return; } closefunc = NULL; - oldintr = NULL; - oldintp = NULL; tcrflag = !crflag && is_retr; - if (sigsetjmp(recvabort, 1)) { + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + abortrecv(SIGINT); while (cpend) { (void) getreply(0); } if (data >= 0) { + INTOFF; (void) close(data); data = -1; + INTON; } - if (oldintr) - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } - oldintr = signal(SIGINT, abortrecv); + toplevel = &jmploc; if (strcmp(local, "-") && *local != '|') { if (access(local, W_OK) < 0) { char *dir = rindex(local, '/'); @@ -787,7 +889,7 @@ if (errno != ENOENT && errno != EACCES) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } @@ -799,7 +901,7 @@ if (d < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } @@ -807,24 +909,20 @@ chmod(local, 0600) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - /* - * Believe it or not, this was actually - * repeated in the original source. - */ - (void) signal(SIGINT, oldintr); - /*(void) signal(SIGINT, oldintr);*/ + toplevel = oldtoplevel; code = -1; return; } if (runique && errno == EACCES && (local = gunique(local)) == NULL) { - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } } - else if (runique && (local = gunique(local)) == NULL) { - (void) signal(SIGINT, oldintr); + else if (runique && (strcmp(cmd,"NLST") != 0) && + (local = gunique(local)) == NULL) { + toplevel = oldtoplevel; code = -1; return; } @@ -837,74 +935,84 @@ changetype(type, 0); } if (initconn()) { - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; code = -1; return; } - if (sigsetjmp(recvabort, 1)) + if (sigsetjmp(jmploc, 1)) { + abortrecv(SIGINT); goto abort; + } if (is_retr && restart_point && - command("REST %ld", (long) restart_point) != CONTINUE) + command("REST %jd", (intmax_t) restart_point) != CONTINUE) { + toplevel = oldtoplevel; return; + } if (remote) { if (command("%s %s", cmd, remote) != PRELIM) { - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; return; } } else { if (command("%s", cmd) != PRELIM) { - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; return; } } + INTOFF; din = dataconn("r"); + INTON; if (din == NULL) goto abort; - if (strcmp(local, "-") == 0) + if (strcmp(local, "-") == 0) { fout = stdout; + tqcflag = qcflag; + } else if (*local == '|') { - oldintp = signal(SIGPIPE, SIG_IGN); + closefunc = pclose; + INTOFF; fout = popen(local + 1, "w"); + INTON; if (fout == NULL) { perror(local+1); goto abort; } - closefunc = pclose; } else { + closefunc = fclose; + INTOFF; fout = fopen(local, lmode); + INTON; if (fout == NULL) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); goto abort; } - closefunc = fclose; } if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) - st.st_blksize = BUFSIZ; - if (st.st_blksize > bufsize) { - if (buf) - (void) free(buf); - buf = malloc((unsigned)st.st_blksize); - if (buf == NULL) { - perror("malloc"); - bufsize = 0; - goto abort; - } + bufsize = BUFSIZ; + else bufsize = st.st_blksize; - } + INTOFF; + buf = obstack_alloc(&mainobstack, bufsize); + INTON; (void) gettimeofday(&start, (struct timezone *)0); switch (curtype) { case TYPE_I: case TYPE_L: if (restart_point && - lseek(fileno(fout), (long) restart_point, L_SET) < 0) { + lseek(fileno(fout), restart_point, L_SET) < 0) { fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fout); + fout = NULL; + INTON; + } + toplevel = oldtoplevel; return; } errno = d = 0; @@ -920,9 +1028,7 @@ (void) fflush(stdout); } if (tick && (bytes >= hashbytes) && is_retr) { - (void) printf("\rBytes transferred: %ld", - bytes); - (void) fflush(stdout); + printbytes(bytes); while (bytes >= hashbytes) hashbytes += TICKBYTES; } @@ -934,12 +1040,10 @@ (void) fflush(stdout); } if (tick && is_retr) { - (void) printf("\rBytes transferred: %ld\n", bytes); - (void) fflush(stdout); + printbytes(bytes); } if (c < 0) { - if (errno != EPIPE) - perror("netin"); + perror("netin"); bytes = -1; } if (d < c) { @@ -968,8 +1072,13 @@ done: fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fout); + fout = NULL; + INTON; + } + toplevel = oldtoplevel; return; } } @@ -984,9 +1093,7 @@ hashbytes += HASHBYTES; } if (tick && (bytes >= hashbytes) && is_retr) { - printf("\rBytes transferred: %ld", - bytes); - fflush(stdout); + printbytes(bytes); while (bytes >= hashbytes) hashbytes += TICKBYTES; } @@ -1003,6 +1110,8 @@ goto contin2; } } + if (tqcflag && !isprint(c) && !isspace(c)) + c = '?'; (void) putc(c, fout); bytes++; contin2: ; @@ -1015,16 +1124,14 @@ (void) fflush(stdout); } if (tick && is_retr) { - (void) printf("\rBytes transferred: %ld\n", bytes); - (void) fflush(stdout); + printbytes(bytes); } if (bare_lfs) { printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); printf("File may not have transferred correctly.\n"); } if (ferror(din)) { - if (errno != EPIPE) - perror("netin"); + perror("netin"); bytes = -1; } if (ferror(fout)) @@ -1032,15 +1139,19 @@ strerror(errno)); break; } - if (closefunc != NULL) + if (closefunc != NULL) { + INTOFF; (*closefunc)(fout); - (void) signal(SIGINT, oldintr); - if (oldintp) - (void) signal(SIGPIPE, oldintp); - (void) gettimeofday(&stop, (struct timezone *)0); + fout = NULL; + INTON; + } + INTOFF; (void) fclose(din); /* closes data as well, so discard it */ data = -1; + INTON; + toplevel = oldtoplevel; + (void) gettimeofday(&stop, (struct timezone *)0); (void) getreply(0); if (bytes > 0 && is_retr) ptransfer("received", bytes, &start, &stop); @@ -1050,30 +1161,34 @@ /* abort using RFC959 recommended IP,SYNC sequence */ (void) gettimeofday(&stop, (struct timezone *)0); - if (oldintp) - (void) signal(SIGPIPE, oldintp); - (void) signal(SIGINT, SIG_IGN); + INTOFF; if (!cpend) { code = -1; - (void) signal(SIGINT, oldintr); + INTON; + toplevel = oldtoplevel; return; } abort_remote(din); code = -1; - if (closefunc != NULL && fout != NULL) + if (closefunc != NULL && fout != NULL) { (*closefunc)(fout); + fout = NULL; + } if (din) { + if (data == fileno(din)) + data = -1; (void) fclose(din); + din = NULL; } if (data >= 0) { - /* if it just got closed with din, again won't hurt */ (void) close(data); data = -1; } if (bytes > 0) ptransfer("received", bytes, &start, &stop); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; + INTON; } /* @@ -1091,7 +1206,11 @@ u_long a1,a2,a3,a4,p1,p2; if (passivemode) { + INTOFF; + if (data >= 0) + close(data); data = socket(AF_INET, SOCK_STREAM, 0); + INTON; if (data < 0) { perror("ftp: socket"); return(1); @@ -1143,9 +1262,11 @@ data_addr = myctladdr; if (sendport) data_addr.sin_port = 0; /* let system pick one */ + INTOFF; if (data != -1) (void) close(data); data = socket(AF_INET, SOCK_STREAM, 0); + INTON; if (data < 0) { perror("ftp: socket"); if (tmpno) @@ -1195,7 +1316,9 @@ #endif return (0); bad: + INTOFF; (void) close(data), data = -1; + INTON; if (tmpno) sendport = 1; return (1); @@ -1228,7 +1351,7 @@ } static void -ptransfer(const char *direction, long bytes, +ptransfer(const char *direction, off_t bytes, const struct timeval *t0, const struct timeval *t1) { @@ -1240,8 +1363,8 @@ s = td.tv_sec + (td.tv_usec / 1000000.); #define nz(x) ((x) == 0 ? 1 : (x)) bs = bytes / nz(s); - printf("%ld bytes %s in %.3g secs (%.2g Kbytes/sec)\n", - bytes, direction, s, bs / 1024.0); + printf("%jd bytes %s in %.2f secs (%.1f kB/s)\n", + (intmax_t) bytes, direction, s, bs / 1024.0); } } @@ -1269,18 +1392,9 @@ tdiff->tv_sec--, tdiff->tv_usec += 1000000; } -static -void -psabort(int ignore) -{ - (void)ignore; - abrtflag++; -} - void pswitch(int flag) { - void (*oldintr)(int); static struct comvars { int connect; char name[MAXHOSTNAMELEN]; @@ -1303,11 +1417,10 @@ } proxstruct, tmpstruct; struct comvars *ip, *op; - abrtflag = 0; - oldintr = signal(SIGINT, psabort); if (flag) { if (proxy) return; + INTOFF; ip = &tmpstruct; op = &proxstruct; proxy++; @@ -1315,6 +1428,7 @@ else { if (!proxy) return; + INTOFF; ip = &proxstruct; op = &tmpstruct; proxy = 0; @@ -1323,7 +1437,7 @@ connected = op->connect; if (hostname) { (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); - ip->name[strlen(ip->name)] = '\0'; + ip->name[sizeof(ip->name) - 1] = '\0'; } else { ip->name[0] = 0; @@ -1351,25 +1465,21 @@ mcase = op->mcse; ip->ntflg = ntflag; ntflag = op->ntflg; - (void) strncpy(ip->nti, ntin, 16); - (ip->nti)[strlen(ip->nti)] = '\0'; + (void) strncpy(ip->nti, ntin, sizeof(ip->nti) - 1); + (ip->nti)[sizeof(ip->nti) - 1] = '\0'; (void) strcpy(ntin, op->nti); - (void) strncpy(ip->nto, ntout, 16); - (ip->nto)[strlen(ip->nto)] = '\0'; + (void) strncpy(ip->nto, ntout, sizeof(ip->nto) - 1); + (ip->nto)[sizeof(ip->nto) - 1] = '\0'; (void) strcpy(ntout, op->nto); ip->mapflg = mapflag; mapflag = op->mapflg; - (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); - (ip->mi)[strlen(ip->mi)] = '\0'; + (void) strncpy(ip->mi, mapin, sizeof(ip->mi) - 1); + (ip->mi)[sizeof(ip->mi) - 1] = '\0'; (void) strcpy(mapin, op->mi); - (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); - (ip->mo)[strlen(ip->mo)] = '\0'; + (void) strncpy(ip->mo, mapout, sizeof(ip->mo) - 1); + (ip->mo)[sizeof(ip->mo) - 1] = '\0'; (void) strcpy(mapout, op->mo); - (void) signal(SIGINT, oldintr); - if (abrtflag) { - abrtflag = 0; - (*oldintr)(SIGINT); - } + INTON; } static @@ -1381,17 +1491,16 @@ fflush(stdout); ptabflg++; mflag = 0; - abrtflag = 0; - siglongjmp(ptabort, 1); } static void proxtrans(const char *cmd, char *local, char *remote) { - void (*volatile oldintr)(int); volatile int secndflag = 0, prox_type, nfnd; const char *volatile cmd2; fd_set mask; + sigjmp_buf jmploc; + sigjmp_buf *volatile oldtoplevel; if (strcmp(cmd, "RETR")) cmd2 = "RETR"; @@ -1422,11 +1531,14 @@ pswitch(1); return; } - if (sigsetjmp(ptabort, 1)) + oldtoplevel = toplevel; + if (sigsetjmp(jmploc, 1)) { + abortpt(SIGINT); goto abort; - oldintr = signal(SIGINT, abortpt); + } + toplevel = &jmploc; if (command("%s %s", cmd, remote) != PRELIM) { - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; pswitch(1); return; } @@ -1439,13 +1551,13 @@ (void) getreply(0); pswitch(0); (void) getreply(0); - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; pswitch(1); ptflag = 0; printf("local: %s remote: %s\n", local, remote); return; abort: - (void) signal(SIGINT, SIG_IGN); + INTOFF; ptflag = 0; if (strcmp(cmd, "RETR") && !proxy) pswitch(1); @@ -1460,7 +1572,8 @@ pswitch(1); if (ptabflg) code = -1; - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; + INTON; return; } if (cpend) @@ -1474,7 +1587,8 @@ pswitch(1); if (ptabflg) code = -1; - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; + INTON; return; } } @@ -1500,7 +1614,8 @@ pswitch(1); if (ptabflg) code = -1; - (void) signal(SIGINT, oldintr); + toplevel = oldtoplevel; + INTON; } void @@ -1515,7 +1630,9 @@ if ((nfnd = empty(&mask, fileno(cin), 0)) < 0) { perror("reset"); code = -1; + INTOFF; lostpeer(0); + INTON; } else if (nfnd) { (void) getreply(0); @@ -1572,26 +1689,30 @@ abort_remote(FILE *din) { char buf[BUFSIZ]; - int nfnd, hifd; + int nfnd, hifd = -1; fd_set mask; /* * send IAC in urgent mode instead of DM because 4.3BSD places oob mark * after urgent byte rather than before as is protocol now */ - snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC); - if (send(fileno(cout), buf, 3, MSG_OOB) != 3) - perror("abort"); - fprintf(cout,"%cABOR\r\n", DM); - (void) fflush(cout); + if (cout) { + snprintf(buf, sizeof(buf), "%c%c%c", IAC, IP, IAC); + if (send(fileno(cout), buf, 3, MSG_OOB) != 3) + perror("abort"); + fprintf(cout,"%cABOR\r\n", DM); + (void) fflush(cout); + } FD_ZERO(&mask); - FD_SET(fileno(cin), &mask); - hifd = fileno(cin); + if (cin) { + FD_SET(fileno(cin), &mask); + hifd = fileno(cin); + } if (din) { FD_SET(fileno(din), &mask); if (hifd < fileno(din)) hifd = fileno(din); } - if ((nfnd = empty(&mask, hifd, 10)) <= 0) { + if (hifd >= 0 && (nfnd = empty(&mask, hifd, 10)) <= 0) { if (nfnd < 0) { perror("abort"); } @@ -1609,3 +1730,10 @@ } (void) getreply(0); } + +static void +printbytes(off_t bytes) +{ + printf("\rBytes transferred: %jd", (intmax_t) bytes); + fflush(stdout); +} --- netkit-ftp-0.17.orig/ftp/ftp_var.h +++ netkit-ftp-0.17/ftp/ftp_var.h @@ -76,6 +76,7 @@ Extern int mapflag; /* use mapin mapout templates on file names */ Extern int code; /* return/reply code for ftp command */ Extern int crflag; /* if 1, strip car. rets. on ascii gets */ +Extern int qcflag; /* if 1, print ? instead of control chars */ Extern char pasv[64]; /* passive port for proxy data connection */ Extern int passivemode; /* passive mode enabled */ Extern char *altarg; /* argv[1] with no shell-like preprocessing */ @@ -102,11 +103,11 @@ /*Extern struct servent *sp;*/ /* service spec for tcp/ftp */ Extern int ftp_port; /* htons'd port number for ftp service */ -Extern sigjmp_buf toplevel; /* non-local goto stuff for cmd scanner */ +Extern sigjmp_buf *toplevel; /* non-local goto stuff for cmd scanner */ -Extern char line[200]; /* input line buffer */ +Extern char *line; /* input line buffer */ Extern char *stringbase; /* current scan point in line buffer */ -Extern char argbuf[200]; /* argument storage buffer */ +Extern char *argbuf; /* argument storage buffer */ Extern char *argbase; /* current storage point in arg buffer */ Extern int cpend; /* flag: if != 0, then pending server reply */ Extern int mflag; /* flag: if != 0, then active multi command */ --- netkit-ftp-0.17.orig/ftp/main.c +++ netkit-ftp-0.17/ftp/main.c @@ -60,6 +60,7 @@ #include #include #include +#include #ifdef __USE_READLINE__ #include #include @@ -67,9 +68,21 @@ #define Extern #include "ftp_var.h" +#include "main.h" + +#define obstack_chunk_alloc malloc +#define obstack_chunk_free free + int traceflag = 0; const char *home = "/"; +int suppressint; +volatile int intpending; +int intrnewline; +struct obstack mainobstack; +struct obstack lineobstack; + +extern FILE *cin; extern FILE *cout; extern int data; extern struct cmd cmdtab[]; @@ -79,8 +92,10 @@ void lostpeer(int); void help(int argc, char *argv[]); +static void inthandler(int); static void cmdscanner(int top); static char *slurpstring(void); +static void resetstack(struct obstack *); static void @@ -106,6 +121,7 @@ int top; struct passwd *pw = NULL; char homedir[MAXPATHLEN]; + sigjmp_buf jmploc; tick = 0; @@ -125,13 +141,6 @@ if (strcmp(cp, "pftp") == 0) passivemode = 1; -#ifdef __USE_READLINE__ - /* - * Set terminal type so libreadline can parse .inputrc correctly - */ - rl_terminal_name = getenv("TERM"); -#endif - argc--, argv++; while (argc > 0 && **argv == '-') { for (cp = *argv + 1; *cp; cp++) @@ -182,12 +191,23 @@ argc--, argv++; } fromatty = isatty(fileno(stdin)); + +#ifdef __USE_READLINE__ + /* + * Set terminal type so libreadline can parse .inputrc correctly + */ + if (fromatty && !rl_inhibit) { + rl_terminal_name = getenv("TERM"); + } +#endif + if (fromatty) verbose++; cpend = 0; /* no pending replies */ proxy = 0; /* proxy not active */ crflag = 1; /* strip c.r. on ascii gets */ sendport = -1; /* not using ports */ + qcflag = isatty(fileno(stdout)); /* * Set up the home directory in case we're globbing. */ @@ -202,17 +222,33 @@ homedir[sizeof(homedir)-1] = 0; home = homedir; } + /* + * We need this since we want to return from unsafe library calls ASAP + * when a SIGINT happens. + */ + siginterrupt(SIGINT, 1); + toplevel = &jmploc; + obstack_init(&mainobstack); + obstack_init(&lineobstack); if (argc > 0) { - if (sigsetjmp(toplevel, 1)) + if (sigsetjmp(jmploc, 1)) exit(0); - (void) signal(SIGINT, intr); - (void) signal(SIGPIPE, lostpeer); + (void) signal(SIGINT, inthandler); + (void) signal(SIGPIPE, SIG_IGN); setpeer(argc + 1, argv - 1); + resetstack(&mainobstack); + resetstack(&lineobstack); } - top = sigsetjmp(toplevel, 1) == 0; + top = sigsetjmp(jmploc, 1) == 0; if (top) { - (void) signal(SIGINT, intr); - (void) signal(SIGPIPE, lostpeer); + (void) signal(SIGINT, inthandler); + (void) signal(SIGPIPE, SIG_IGN); + } else { + INTOFF; + resetstack(&mainobstack); + resetstack(&lineobstack); + INTON; + pswitch(0); } for (;;) { cmdscanner(top); @@ -224,9 +260,28 @@ intr(int ignore) { (void)ignore; - siglongjmp(toplevel, 1); + + intpending = 0; + siglongjmp(*toplevel, 1); +} + +static void +inthandler(int sig) +{ + if (intrnewline) { + putchar('\n'); + fflush(stdout); + } + if (suppressint) { + intpending++; + return; + } + intr(sig); } +/* + * Must be called with interrupts off. + */ void lostpeer(int ignore) { @@ -238,6 +293,10 @@ fclose(cout); cout = NULL; } + if (cin != NULL) { + fclose(cin); + cin = NULL; + } if (data >= 0) { shutdown(data, 1+1); close(data); @@ -252,6 +311,10 @@ fclose(cout); cout = NULL; } + if (cin != NULL) { + fclose(cin); + cin = NULL; + } connected = 0; } proxflag = 0; @@ -276,24 +339,40 @@ } */ -static char *get_input_line(char *buf, int buflen) +static char *get_input_line(void) { + char *lineread; + size_t size; + ssize_t len; + #ifdef __USE_READLINE__ if (fromatty && !rl_inhibit) { - char *lineread = readline("ftp> "); - if (!lineread) return NULL; - strncpy(buf, lineread, buflen); - buf[buflen-1] = 0; + lineread = readline("ftp> "); + INTOFF; + if (!lineread) goto err; if (lineread[0]) add_history(lineread); - free(lineread); - return buf; + len = strlen(lineread); + goto out; } #endif if (fromatty) { printf("ftp> "); fflush(stdout); } - return fgets(buf, buflen, stdin); + size = 0; + lineread = 0; + INTOFF; + len = getline(&lineread, &size, stdin); + if (len == -1 || !lineread) { +err: + INTON; + return NULL; + } +out: + line = obstack_copy(&lineobstack, lineread, len + 1); + free (lineread); + INTON; + return line; } @@ -308,11 +387,19 @@ char **margv; register struct cmd *c; register int l; + int first = 1; if (!top) (void) putchar('\n'); for (;;) { - if (!get_input_line(line, sizeof(line))) { + if (!first) { + INTOFF; + obstack_free(&lineobstack, line); + resetstack(&mainobstack); + INTON; + } + first = 0; + if (!get_input_line()) { quit(); } l = strlen(line); @@ -323,12 +410,6 @@ break; line[l] = '\0'; } - else if (l == sizeof(line) - 2) { - printf("sorry, input line too long\n"); - while ((l = getchar()) != '\n' && l != EOF) - /* void */; - break; - } /* else it was a line without a newline */ margv = makeargv(&margc, &marg); if (margc == 0) { continue; @@ -354,8 +435,10 @@ if (c->c_handler_v != help) break; } - (void) signal(SIGINT, intr); - (void) signal(SIGPIPE, lostpeer); + INTOFF; + obstack_free(&lineobstack, line); + resetstack(&mainobstack); + INTON; } struct cmd * @@ -399,6 +482,9 @@ int rargc = 0; char **argp; + INTOFF; + argbuf = obstack_alloc(&mainobstack, strlen(line) + 1); + INTON; argp = rargv; stringbase = line; /* scan from first of buffer */ argbase = argbuf; /* store from first of buffer */ @@ -602,3 +688,10 @@ c->c_name, c->c_help); } } + +static void +resetstack(struct obstack *stack) +{ + obstack_free(stack, 0); + obstack_init(stack); +} --- netkit-ftp-0.17.orig/ftp/netrc.5 +++ netkit-ftp-0.17/ftp/netrc.5 @@ -37,8 +37,10 @@ .Dt NETRC 5 .Os "Linux NetKit (0.17)" .Sh NAME -.Nm netrc, .netrc +.Nm netrc .Nd user configuration for ftp +.Sh SYNOPSIS +.Nm ~/.netrc .Sh DESCRIPTION This file contains configuration and autologin information for the File Transfer Protocol client --- netkit-ftp-0.17.orig/ftp/ruserpass.c +++ netkit-ftp-0.17/ftp/ruserpass.c @@ -46,6 +46,7 @@ #include #include #include "ftp_var.h" +#include "main.h" static FILE *cfile; static int token(void); @@ -136,8 +137,7 @@ case LOGIN: if (token()) { if (*aname == 0) { - *aname = malloc((unsigned) strlen(tokval) + 1); - (void) strcpy(*aname, tokval); + *aname = obstack_copy(&mainobstack, tokval, strlen(tokval) + 1); } else { if (strcmp(*aname, tokval)) goto next; @@ -157,8 +157,7 @@ goto bad; } if (token() && *apass == 0) { - *apass = malloc((unsigned) strlen(tokval) + 1); - (void) strcpy(*apass, tokval); + *apass = obstack_copy(&mainobstack, tokval, strlen(tokval) + 1); } break; case ACCOUNT: @@ -169,8 +168,7 @@ goto bad; } if (token() && *aacct == 0) { - *aacct = malloc((unsigned) strlen(tokval) + 1); - (void) strcpy(*aacct, tokval); + *aacct = obstack_copy(&mainobstack, tokval, strlen(tokval) + 1); } break; case MACDEF: --- netkit-ftp-0.17.orig/ftp/main.h +++ netkit-ftp-0.17/ftp/main.h @@ -0,0 +1,20 @@ +#include +#include + +extern int suppressint; +extern volatile int intpending; +extern int intrnewline; +extern struct obstack mainobstack; +extern struct obstack lineobstack; + +#ifdef __GNUC__ +void intr(int) __attribute__ ((noreturn)); +#else +void intr(int); +#endif + +#define INTOFF suppressint++; +#define INTON do { if (--suppressint == 0 && intpending) intr(SIGINT); } \ + while(0) +#define CHECKINT do { if (suppressint == 1 && intpending) { \ + suppressint = 0; intr(SIGINT); }} while(0) debian/patches/041_user_address_commands.diff0000644000000000000000000001362311553372357016417 0ustar Description: Improve user interface with address family selection. Implement command line options for selecting IPv4 or IPv6. . Implement runtime command 'ipany', 'ipv4', and 'ipv6'. These allow repeatedly new selection of addressing mode. Author: Mats Erik Andersson Forwarded: no Last-Update: 2011-04-19 diff -Nru netkit-ftp-0.17.debian/ftp/cmds.c netkit-ftp-0.17/ftp/cmds.c --- netkit-ftp-0.17.debian/ftp/cmds.c +++ netkit-ftp-0.17/ftp/cmds.c @@ -1106,6 +1106,9 @@ } pswitch(0); } + printf("Connecting using address family: %s.\n", + (usefamily == AF_UNSPEC) ? "any" + : (usefamily == AF_INET6) ? "IPv6" : "IPv4"); printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", modename, typename, formname, structname); printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", @@ -2389,6 +2392,39 @@ } /* + * Set unrestricted address resolving + */ +void +setipany(void) +{ + usefamily = AF_UNSPEC; + printf("Chosen addressing: %s.\n", "any"); + code = usefamily; +} + +/* + * Resolve only to IPv4 addressing + */ +void +setipv4(void) +{ + usefamily = AF_INET; + printf("Chosen addressing: %s.\n", "IPv4"); + code = usefamily; +} + +/* + * Resolve only to IPv4 addressing + */ +void +setipv6(void) +{ + usefamily = AF_INET6; + printf("Chosen addressing: %s.\n", "IPv6"); + code = usefamily; +} + +/* * get size of file on remote machine */ void diff -Nru netkit-ftp-0.17.debian/ftp/cmds.h netkit-ftp-0.17/ftp/cmds.h --- netkit-ftp-0.17.debian/ftp/cmds.h +++ netkit-ftp-0.17/ftp/cmds.h @@ -8,6 +8,9 @@ void setform(void); void setglob(void); void sethash(void); +void setipany(void); +void setipv4(void); +void setipv6(void); void setmode(void); void setport(void); void setprompt(void); diff -Nru netkit-ftp-0.17.debian/ftp/cmdtab.c netkit-ftp-0.17/ftp/cmdtab.c --- netkit-ftp-0.17.debian/ftp/cmdtab.c +++ netkit-ftp-0.17/ftp/cmdtab.c @@ -67,6 +67,9 @@ const char hashhelp[] = "toggle printing `#' for each buffer transferred"; const char helphelp[] = "print local help information"; const char idlehelp[] = "get (set) idle timer on remote side"; +const char ipanyhelp[] = "allow use of any address family"; +const char ipv4help[] = "restrict address usage to IPv4"; +const char ipv6help[] = "restrict address usage to IPv6"; const char lcdhelp[] = "change local working directory"; const char lshelp[] = "list contents of remote directory"; const char macdefhelp[] = "define a macro"; @@ -142,6 +145,9 @@ { "help", helphelp, 0, 0, 1, help, NULL, NULL }, { "idle", idlehelp, 0, 1, 1, idle_cmd, NULL, NULL }, { "image", binaryhelp, 0, 1, 1, NULL, setbinary, NULL }, + { "ipany", ipanyhelp, 0, 0, 0, NULL, setipany, NULL }, + { "ipv4", ipv4help, 0, 0, 0, NULL, setipv4, NULL }, + { "ipv6", ipv6help, 0, 0, 0, NULL, setipv6, NULL }, { "lcd", lcdhelp, 0, 0, 0, lcd, NULL, NULL }, { "ls", lshelp, 1, 1, 1, ls, NULL, NULL }, { "macdef", macdefhelp, 0, 0, 0, macdef, NULL, NULL }, diff -Nru netkit-ftp-0.17.debian/ftp/ftp.1 netkit-ftp-0.17/ftp/ftp.1 --- netkit-ftp-0.17.debian/ftp/ftp.1 +++ netkit-ftp-0.17/ftp/ftp.1 @@ -42,10 +42,10 @@ file transfer program .Sh SYNOPSIS .Nm ftp -.Op Fl pinegvd +.Op Fl 46pinegvd .Op Ar host Op Ar port .Nm pftp -.Op Fl inegvd +.Op Fl 46inegvd .Op Ar host Op Ar port .Sh DESCRIPTION .Nm Ftp @@ -58,6 +58,10 @@ Options may be specified at the command line, or to the command interpreter. .Bl -tag -width flag +.It Fl 4 +Use only IPv4 to contact any host. +.It Fl 6 +Use IPv6 only. .It Fl p Use passive mode for data transfers. Allows use of ftp in environments where a firewall prevents connections from the outside world back to @@ -344,6 +348,12 @@ If .Ar seconds is omitted, the current inactivity timer is printed. +.It Ic ipany +Allow the address resolver to return any address family. +.It Ic ipv4 +Restrict the address resolver to look only for IPv4 addresses. +.It Ic ipv6 +Restrict host adressing to IPv6 only. .It Ic lcd Op Ar directory Change the working directory on the local machine. If diff -Nru netkit-ftp-0.17.debian/ftp/ftp.c netkit-ftp-0.17/ftp/ftp.c --- netkit-ftp-0.17.debian/ftp/ftp.c +++ netkit-ftp-0.17/ftp/ftp.c @@ -132,7 +132,7 @@ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; - hints.ai_family = AF_UNSPEC; + hints.ai_family = usefamily; hints.ai_socktype = SOCK_STREAM; if ( (status = getaddrinfo(host, NULL, &hints, &ai)) ) { diff -Nru netkit-ftp-0.17.debian/ftp/ftp_var.h netkit-ftp-0.17/ftp/ftp_var.h --- netkit-ftp-0.17.debian/ftp/ftp_var.h +++ netkit-ftp-0.17/ftp/ftp_var.h @@ -61,6 +61,7 @@ Extern int sendport; /* use PORT cmd for each data connection */ Extern int verbose; /* print messages coming back from server */ Extern int connected; /* connected to server */ +Extern int usefamily; /* address family for resolving */ Extern int fromatty; /* input is from a terminal */ Extern int interactive; /* interactively prompt on m* cmds */ Extern int debug; /* debugging level */ diff -Nru netkit-ftp-0.17.debian/ftp/main.c netkit-ftp-0.17/ftp/main.c --- netkit-ftp-0.17.debian/ftp/main.c +++ netkit-ftp-0.17/ftp/main.c @@ -101,7 +101,9 @@ void usage(void) { - printf("\n\tUsage: { ftp | pftp } [-pinegvtd] [hostname]\n"); + printf("\n\tUsage: { ftp | pftp } [-46pinegvtd] [hostname]\n"); + printf("\t -4: use IPv4 addresses only\n"); + printf("\t -6: use IPv6, nothing else\n"); printf("\t -p: enable passive mode (default for pftp)\n"); printf("\t -i: turn off prompting during mget\n"); printf("\t -n: inhibit auto-login\n"); @@ -135,6 +137,7 @@ interactive = 1; autologin = 1; passivemode = 0; + usefamily = AF_UNSPEC; /* the default is to allow any family */ cp = strrchr(argv[0], '/'); cp = (cp == NULL) ? argv[0] : cp+1; @@ -146,6 +149,14 @@ for (cp = *argv + 1; *cp; cp++) switch (*cp) { + case '4': + usefamily = AF_INET; + break; + + case '6': + usefamily = AF_INET6; + break; + case 'd': options |= SO_DEBUG; debug++; debian/patches/035_lintian_pedantic.diff0000644000000000000000000000311311354404035015340 0ustar Description: Pedantic complaits by lintian. Spelling in ftp/ftp.1 and ftp/cmds.c. . Incorrect use of hyphenation in ftp/ftp.1. Author: Mats Erik Andersson Forwarded: no Last-Update: 2010-02-27 --- netkit-ftp-0.17/ftp/ftp.1.debian +++ netkit-ftp-0.17/ftp/ftp.1 @@ -343,7 +343,7 @@ seconds. If .Ar seconds -is ommitted, the current inactivity timer is printed. +is omitted, the current inactivity timer is printed. .It Ic lcd Op Ar directory Change the working directory on the local machine. If @@ -854,7 +854,7 @@ .Ar newmask . If .Ar newmask -is ommitted, the current umask is printed. +is omitted, the current umask is printed. .It Xo .Ic user Ar user-name .Op Ar password @@ -957,7 +957,7 @@ (stdin). If the shell command includes spaces, the argument must be quoted; e.g. -\*(Lq" ls -lt"\*(Rq. +\*(Lq" ls \-lt"\*(Rq. A particularly useful example of this mechanism is: \*(Lqdir more\*(Rq. .It @@ -1010,9 +1010,9 @@ .Ic type may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary), \*(Lqebcdic\*(Rq, and \*(Lqlocal byte size\*(Rq (for -.Tn PDP Ns -10's +.Tn PDP Ns \-10's and -.Tn PDP Ns -20's +.Tn PDP Ns \-20's mostly). .Nm Ftp supports the ascii and image types of file transfer, --- netkit-ftp-0.17/ftp/cmds.c.debian +++ netkit-ftp-0.17/ftp/cmds.c @@ -2511,7 +2511,7 @@ if (overbose && !strncmp(reply_string, "215 TOPS20", 10)) printf( -"Remember to set tenex mode when transfering binary files from this machine.\n"); +"Remember to set tenex mode when transferring binary files from this machine.\n"); } verbose = overbose; #else debian/patches/050_support_gnu_hurd.diff0000644000000000000000000000335311734446501015453 0ustar Description: Support GNU/Hurd Add fall-back macro definitions for PATH_MAX, MAXPATHLEN, and MAXHOSTNAMELEN, all of which are not specified by POSIX, hence are legally missing for GNU/Hurd. . Replace a few uses of these macros by "sizeof()", in order to improve robustness of their value. Since PATH_MAX and MAXPATHLEN are implicitly assumed to be equal. Author: Mats Erik Andersson Forwarded: no Last-Update: 2012-03-28 --- netkit-ftp-0.17.debian/ftp/ftp_var.h +++ netkit-ftp-0.17/ftp/ftp_var.h @@ -42,6 +42,24 @@ #include /* + * The following macros are non-POSIX, and are missing + * for GNU/Hurd. They are used statically in the present + * source code, so the values have been borrowed from + * Glibc as present in GNU/kFreeBSD. + */ +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +#ifndef MAXPATHLEN +# define MAXPATHLEN PATH_MAX +#endif + +#ifndef MAXHOSTNAMELEN +# define MAXHOSTNAMELEN 256 +#endif + +/* * Tick counter step size. */ #define TICKBYTES 10240 --- netkit-ftp-0.17.debian/ftp/cmds.c +++ netkit-ftp-0.17/ftp/cmds.c @@ -1041,7 +1041,7 @@ for (sp = pattern, nrslash = 0; sp != 0; sp = strchr(sp, '/')) { while (*sp == '/') sp++; - if (nrslash >= MAXPATHLEN) { + if (nrslash >= sizeof(dotdot)) { printf("Incredible pattern: %s\n", pattern); return 0; } @@ -2095,11 +2095,11 @@ cp = index(altarg, ' '); } *cp = '\0'; - (void) strncpy(mapin, altarg, PATH_MAX - 1); - mapin[PATH_MAX-1] = 0; + (void) strncpy(mapin, altarg, sizeof(mapin) - 1); + mapin[sizeof(mapin)-1] = 0; while (*++cp == ' '); - (void) strncpy(mapout, cp, PATH_MAX - 1); - mapout[PATH_MAX-1] = 0; + (void) strncpy(mapout, cp, sizeof(mapout) - 1); + mapout[sizeof(mapout)-1] = 0; } static debian/patches/030_argv_handling.diff0000644000000000000000000000604511354404035014640 0ustar Description: Multiple flaws in ftp/main.c. There are several flaws in the current code of the makeargv function in ftp/main.c. It certainly errs, but not on the side of caution. . 1. The 'count' variable is supposed to count the number of arguments on the command line. In fact it counts the number of arguments less one, so malloc is often called with an argument of zero. . 2. The argument to malloc is completely wrong. Space needs to be reserved for a certain number of pointers; the length of the command line string is irrelevant. . 3. The slurpstring parsing function accepts both space and tab as delimiters. The 'count' variable is calculated assuming spaces only. . 4. It appears to me that the memory allocated for rargv is never freed, leading to a memory leak. I may be wrong about this, and I do not know the code well enough to suggest where the free should take place if it does not happen already. My patch does not address this. . Attempting to count parameters in advance is not the best solution in my opinion. It is duplicating part of the effort of slurpstring. My preference would have been to allocate memory for 20 pointers, as in the original code, then realloc() for a larger size if more than 20 parameters are returned from slurpstring. X-Closes: Closes #508378, #505533, #510009 X-Comment: debdiff netkit-ftp_0.17-{18,19}.dsc Description collected from #508378 Author: Mark Calderbank Forwarded: no Last-Update: 2009-09-14 diff -u netkit-ftp-0.17/ftp/main.c netkit-ftp-0.17/ftp/main.c --- netkit-ftp-0.17/ftp/main.c +++ netkit-ftp-0.17/ftp/main.c @@ -479,23 +479,15 @@ makeargv(int *pargc, char **parg) { static char **rargv = NULL; + static int arglimit = 0; int rargc = 0; - int i = 0, count = 0; char **argp; - - /* Allocate enough space: err on the side of caution */ - while ( line[i] != '\0' ) { - if ( line[i] == ' ' ) - count += 1 ; - i+= 1; - } - - /* allocate memory for $count-sized array of chars */ - rargv = (char **) malloc( count * strlen(line)); - if (rargv == NULL) - fatal("Out of memory"); - + if (arglimit == 0) { + arglimit = 10; + rargv = malloc(arglimit * sizeof(char*)); + if (rargv == NULL) fatal ("Out of memory"); + } INTOFF; argbuf = obstack_alloc(&mainobstack, strlen(line) + 1); INTON; @@ -503,9 +495,15 @@ stringbase = line; /* scan from first of buffer */ argbase = argbuf; /* store from first of buffer */ slrflag = 0; - while ((*argp++ = slurpstring())!=NULL) + while ((*argp++ = slurpstring())!=NULL) { rargc++; - + if (rargc == arglimit) { + rargv = realloc(rargv, (arglimit+10) * sizeof(char*)); + if (rargv == NULL) fatal ("Out of memory"); + argp = rargv + arglimit; + arglimit += 10; + } + } *pargc = rargc; if (parg) *parg = altarg; return rargv; debian/patches/025_long_cmd_overflow.diff0000644000000000000000000000212611354404035015542 0ustar Description: Buffer overflow caused by long commands. Allocate a sufficient amount of memory to handle many arguments. X-Closes: #391207, #407924 X-Comment: debdiff netkit-ftp_0.17-{16,18}.dsc Description interpreted from #407924 Author: Steve Kemp Forwarded: no Last-Update: 2008-03-26 diff -u netkit-ftp-0.17/ftp/main.c netkit-ftp-0.17/ftp/main.c --- netkit-ftp-0.17/ftp/main.c +++ netkit-ftp-0.17/ftp/main.c @@ -478,10 +478,24 @@ char ** makeargv(int *pargc, char **parg) { - static char *rargv[20]; + static char **rargv = NULL; int rargc = 0; + int i = 0, count = 0; char **argp; + + /* Allocate enough space: err on the side of caution */ + while ( line[i] != '\0' ) { + if ( line[i] == ' ' ) + count += 1 ; + i+= 1; + } + + /* allocate memory for $count-sized array of chars */ + rargv = (char **) malloc( count * strlen(line)); + if (rargv == NULL) + fatal("Out of memory"); + INTOFF; argbuf = obstack_alloc(&mainobstack, strlen(line) + 1); INTON; debian/patches/020_optional_stripping.diff0000644000000000000000000000130511354404035015752 0ustar Description: Hard coded stripping behaviour. Remove explicit stripping from makefile target. X-Closes: #437615 X-Comment: debdiff netkit-ftp_0.17-{12,16}.dsc Author: Alberto Gonzalez Iniesta Forwarded: no Last-Update: 2008-03-21 diff -u netkit-ftp-0.17/ftp/Makefile netkit-ftp-0.17/ftp/Makefile --- netkit-ftp-0.17/ftp/Makefile +++ netkit-ftp-0.17/ftp/Makefile @@ -16,7 +16,7 @@ cmds.o glob.o: glob.h install: ftp - install -s -m$(BINMODE) ftp $(INSTALLROOT)$(BINDIR) + install $(INSTALL_OPTS) -m$(BINMODE) ftp $(INSTALLROOT)$(BINDIR) ln -sf ftp $(INSTALLROOT)$(BINDIR)/pftp install -m$(MANMODE) ftp.1 $(INSTALLROOT)$(MANDIR)/man1 ln -sf ftp.1 $(INSTALLROOT)$(MANDIR)/man1/pftp.1 debian/docs0000644000000000000000000000000511253430150010026 0ustar BUGS debian/compat0000644000000000000000000000000211253430150010356 0ustar 7 debian/copyright0000644000000000000000000000452411576742675011152 0ustar Format: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?revision=174 Upstream-Name: netkit-ftp Upstream-Contact: (extinct) Source: ftp://ftp.uk.linux.org/pub/linux/Networking/netkit/ Files: * Copyright: 1985, 1989, 1990, The Regents of the University of California. License: BSD Files: debian/* Copyright: 1999 - 2004, Herbert Xu 2005 - 2011, Alberto Gonzalez Iniesta License: BSD X-Comment: License understood as inherited from source licensing. X-Comment: This package was split from netstd by Herbert Xu on Fri, 18 Jun 1999 21:41:52 +1000. X-Comment: netstd was created by Peter Tobias on Wed, 20 Jul 1994 17:23:21 +0200. Files: debian/patches/040_ipv6_ftp_c.diff Copyright: 2010, Mats Erik Andersson License: BSD X-Comment: The license of the original software is used verbatim for the IPv6-patch. License: BSD Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: . 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. . THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.