Index: Makefile
===================================================================
--- Makefile (nonexistent)
+++ Makefile (revision 5)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url = $(DOWNLOAD_SERVER)/sources/packages/n/netkit-ftp
+
+versions = 0.17
+pkgname = netkit-ftp
+suffix = tar.gz
+
+tarballs = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s = $(addsuffix .sha1sum, $(tarballs))
+
+patches = $(CURDIR)/patches/netkit-ftp-0.17.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+ @echo -e "\n======= Downloading source tarballs =======" ; \
+ for tarball in $(tarballs) ; do \
+ echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+ done ; wait
+
+$(sha1s): $(tarballs)
+ @for sha in $@ ; do \
+ echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+ echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+ touch $$sha ; \
+ echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+ sha1sum --check $$sha ; ret="$$?" ; \
+ if [ "$$ret" == "1" ]; then \
+ echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+ exit 1 ; \
+ fi ; \
+ done
+
+$(patches): $(sha1s)
+ @echo -e "\n======= Create Patches =======\n" ; \
+ ( cd create-0.17-patch ; ./create.patch.sh ) ; \
+ echo -e "\n"
+
+download_clean:
+ @rm -f $(tarballs) $(sha1s) $(patches)
Index: create-0.17-patch/create.patch.sh
===================================================================
--- create-0.17-patch/create.patch.sh (nonexistent)
+++ create-0.17-patch/create.patch.sh (revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=0.17
+
+tar --files-from=file.list -xzvf ../netkit-ftp-$VERSION.tar.gz
+mv netkit-ftp-$VERSION netkit-ftp-$VERSION-orig
+
+cp -rf ./netkit-ftp-$VERSION-new ./netkit-ftp-$VERSION
+
+diff --unified -Nr netkit-ftp-$VERSION-orig netkit-ftp-$VERSION > netkit-ftp-$VERSION.patch
+
+mv netkit-ftp-$VERSION.patch ../patches
+
+rm -rf ./netkit-ftp-$VERSION
+rm -rf ./netkit-ftp-$VERSION-orig
Property changes on: create-0.17-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: create-0.17-patch/file.list
===================================================================
--- create-0.17-patch/file.list (nonexistent)
+++ create-0.17-patch/file.list (revision 5)
@@ -0,0 +1,12 @@
+netkit-ftp-0.17/ChangeLog
+netkit-ftp-0.17/configure
+netkit-ftp-0.17/ftp/Makefile
+netkit-ftp-0.17/ftp/cmds.c
+netkit-ftp-0.17/ftp/cmdtab.c
+netkit-ftp-0.17/ftp/domacro.c
+netkit-ftp-0.17/ftp/ftp.1
+netkit-ftp-0.17/ftp/ftp.c
+netkit-ftp-0.17/ftp/ftp_var.h
+netkit-ftp-0.17/ftp/glob.c
+netkit-ftp-0.17/ftp/main.c
+netkit-ftp-0.17/ftp/ruserpass.c
Index: create-0.17-patch/netkit-ftp-0.17-new/ChangeLog
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ChangeLog (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ChangeLog (revision 5)
@@ -0,0 +1,116 @@
+28-Nov-2000:
+ IPv6 support. (Hiroyuki YAMAMORI <h-yamamo@db3.so-net.ne.jp>)
+
+8-Jul-2000:
+ Fix misused printf-function call (not %n-exploitable though).
+
+14-Dec-1999:
+ netkit-ftp-0.16 is released.
+
+13-Dec-1999:
+ Add fix from Olaf Kirch for some rather severe lossage with
+ aliased file descriptors.
+
+12-Dec-1999:
+ Add Olaf Kirch's ftp mget fix on top of the existing one.
+ Portions of the old fix probably ought to be backed out.
+ However, what's really needed is a massive cleanup of the
+ code...
+
+14-Sep-1999:
+ Extensive small fixes and cleanups. (Alan Curry, pacman@londo.cqc.com)
+ Security fix relating to passive mode. (Alan Cox, alan@redhat.com)
+
+1-Aug-1999:
+ Complete y2k and y2038 audit.
+
+31-Jul-1999:
+ Redid makefiles/config stuff for new confgen version.
+
+23-Sep-1997:
+ Fix some suspicious strncpys.
+ Don't print an uninitialized buffer if someone EOFs at the
+ username prompt. (Olaf Kirch, okir@ns.lst.de)
+ Added a netrc(5) man page.
+ Added -h option to ftp for help, and -e option to inhibit
+ editing support. Cleaned up readline handling.
+ Various fixes to the ftp(1) man page. (Larry Doolittle,
+ ldoolitt@jlab.org)
+
+17-Aug-1997:
+ Fixed security holes: automatically generated local file paths
+ (those that are supplied by the server or copies of server
+ filenames) are filtered so that they cannot:
+ 1. be pipes or "-" for standard output.
+ 2. be absolute paths.
+ 3. contain ".." path elements.
+
+12-Jun-1997:
+ netkit-ftp-0.10 released.
+
+08-Jun-1997:
+ Fixed doc for "newer" command. (Roderick Schertler,
+ roderick@argon.org)
+
+05-Apr-1997:
+ Added configure script to generate MCONFIG.
+ glibc fixes from HJ Lu.
+
+20-Mar-1997:
+ If using readline, pass it the terminal type, so certain .inputrc
+ constructions work. (Christian Groessler, chris@fast-ag.de)
+
+08-Mar-1997:
+ Split from full NetKit package.
+ Generated this change log from NetKit's.
+
+07-Mar-1997
+ Changed order of includes in ftp/cmds.c due to a report of
+ breakage with libc 5.4.x.
+ Fixed crash in ftp caused by certain syntax errors in .netrc.
+ Fix symbol name conflict on "trace" between ftp and ncurses.
+
+29-Dec-1996
+ NetKit-0.09 released.
+ Assorted alpha/glibc patches. (Erik Troan, ewt@redhat.com)
+ Assorted bug fixes from Debian. (Peter Tobias,
+ tobias@et-inf.fho-emden.de)
+ Hardened programs against DNS h_length spoofing attacks.
+ Use inet_aton() everywhere instead of inet_addr().
+ Fixed crash in ftp if you did "lcd" with no args.
+ Fixed bug in ftp where you couldn't abort an mget.
+ Fixed /tmp security problem in ftp.
+
+22-Aug-1996
+ NetKit-B-0.08 released.
+ (almost) everything now compiles with lots of warnings turned on.
+ Fixed some memory allocation bugs in ftp.
+
+25-Jul-1996
+ NetKit-B-0.07A released.
+
+23-Jul-1996
+ NetKit-B-0.07 released.
+ Integrated a collection of patches that had been lurking on the net,
+ including the 256-ptys support for telnetd and passive mode ftp.
+ Major security fixes, including to fingerd, lpr, rlogin, rsh, talkd,
+ and telnetd. Do *not* use the sliplogin from earlier versions of this
+ package, either.
+ Much of the code builds without libbsd.a or bsd includes.
+ Massive code cleanup. Almost everything compiles clean with gcc
+ -Wall now. rusers and rusersd do not; patches to rpcgen to fix
+ this would be appreciated if anyone feels like it.
+ New maintainer: David A. Holland, dholland@hcs.harvard.edu
+
+date not known
+ NetKit-B-0.06 released.
+
+date not known
+ NetKit-B-0.05 released.
+
+date not known
+ NetKit-B-0.04 released.
+
+date not known
+ NetKit-B-0.03 released.
+
Index: create-0.17-patch/netkit-ftp-0.17-new/configure
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/configure (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/configure (revision 5)
@@ -0,0 +1,485 @@
+#!/bin/sh
+#
+# This file was generated by confgen version 2.
+# Do not edit.
+#
+
+PREFIX='/usr'
+#EXECPREFIX='$PREFIX'
+INSTALLROOT=''
+BINMODE='755'
+MANMODE='644'
+
+while [ x$1 != x ]; do case $1 in
+
+ --help)
+ cat <<EOF
+Usage: configure [options]
+ --help Show this message
+ --with-debug Enable debugging
+ --without-readline Disable readline support
+ --prefix=path Prefix for location of files [/usr]
+ --exec-prefix=path Location for arch-depedent files [prefix]
+ --installroot=root Top of filesystem tree to install in [/]
+ --binmode=mode Mode for binaries [755]
+ --manmode=mode Mode for manual pages [644]
+ --with-c-compiler=cc Program for compiling C source [guessed]
+ --enable-ipv6 Enable IPv6 support
+EOF
+ exit 0;;
+ --verbose) ;;
+ --quiet) ;;
+
+ --subdir) . ../configure.defs;;
+
+ --with-debug|--debug) DEBUG=1;;
+ --prefix=*) PREFIX=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --exec-prefix=*) EXECPREFIX=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --installroot=*) INSTALLROOT=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --binmode=*) BINMODE=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --manmode=*) MANMODE=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --with-c-compiler=*) CC=`echo $1 | sed 's/^[^=]*=//'` ;;
+ --without-readline|--disable-readline) WITHOUT_READLINE=1;;
+
+ --disable-ipv6) ENABLE_IPV6=no;;
+ --enable-ipv6=*) ENABLE_IPV6=`echo $1 | sed 's/^[^=]*=//'`;;
+ --enable-ipv6) ENABLE_IPV6=yes;;
+
+ *) echo "Unrecognized option: $1"; exit 1;;
+esac
+shift
+done
+
+if [ x$EXECPREFIX = x ]; then
+ EXECPREFIX="$PREFIX"
+fi
+
+BINDIR="$EXECPREFIX/bin"
+MANDIR="$PREFIX/share/man"
+
+echo "Directories: $BINDIR $MANDIR "
+
+if [ x$INSTALLROOT != x ]; then
+ echo "Installing in chroot tree rooted at $INSTALLROOT"
+fi
+
+##################################################
+
+WARNINGS='-Wall -W -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Winline '
+
+cat << EOF > __conftest.c
+ int main() { int class=0; return class; }
+EOF
+
+if [ x"$CC" = x ]; then
+ echo -n 'Looking for a C compiler... '
+ for TRY in egcs gcc g++ CC c++ cc; do
+ (
+ $TRY __conftest.c -o __conftest || exit 1;
+# ./__conftest || exit 1;
+ ) >/dev/null 2>&1 || continue;
+ CC=$TRY
+ break;
+ done
+ if [ x"$CC" = x ]; then
+ echo 'failed.'
+ echo 'Cannot find a C compiler. Run configure with --with-c-compiler.'
+ rm -f __conftest*
+ exit
+ fi
+ echo "$CC"
+else
+ echo -n 'Checking if C compiler works... '
+ if (
+ $CC __conftest.c -o __conftest || exit 1
+# ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ else
+ echo 'no'
+ echo 'Compiler '"$CC"' does not exist or cannot compile C; try another.'
+ rm -f __conftest*
+ exit
+ fi
+fi
+
+echo -n "Checking if $CC accepts gcc warnings... "
+if (
+ $CC $WARNINGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CC_WARNINGS=1
+else
+ echo 'no'
+fi
+
+if [ x$DEBUG = x ]; then
+ echo -n "Checking if $CC accepts -O2... "
+ if (
+ $CC -O2 __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -O2"
+ else
+ echo 'no'
+ echo -n "Checking if $CC accepts -O... "
+ if (
+ $CC -O __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -O"
+ else
+ echo 'no'
+ fi
+ fi
+
+else
+ echo -n "Checking if $CC accepts -g... "
+ if (
+ $CC -g __conftest.c -o __conftest
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ CFLAGS="$CFLAGS -g"
+ else
+ echo 'no'
+ fi
+
+fi
+
+LDFLAGS=$LDFLAGS
+LIBS=$LIBS
+
+rm -f __conftest*
+
+##################################################
+## Enable IPv6
+echo -n "Whether to enable IPv6 support... "
+if [ x"$ENABLE_IPV6" = x"yes" ]; then
+ echo yes
+ CFLAGS="$CFLAGS -DINET6"
+else
+ echo no
+fi
+
+rm -f __conftest*
+
+## Search IPv6 Library / Headers
+if [ x"$ENABLE_IPV6" = x"yes" ]; then
+ echo -n "Search for IPv6 library... "
+ inet6libdirs="/usr/local/v6/lib /usr/local/lib /usr /usr/inet6/lib"
+ inet6libs="inet6"
+ inet6found=no
+ for inet6libdir in $inet6libdirs; do
+ for inet6lib in $inet6libs; do
+ if [ -d $inet6libdir ] && [ -f $inet6libdir/lib$inet6lib.a ]; then
+ inet6found=yes
+ break 2
+ fi
+ done
+ done
+ if [ x"$inet6found" = x"yes" ]; then
+ echo "$inet6libdir/lib$inet6lib.a"
+ LIBS="$LIBS -L$inet6libdir -l$inet6lib"
+ else
+ echo "not found"
+ fi
+fi
+
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for BSD signal semantics... '
+cat <<EOF >__conftest.c
+#include <unistd.h>
+#include <signal.h>
+volatile int count=0;
+void handle(int foo) { count++; write(1,"X",1);}
+int main() {
+ int pid=getpid();
+ signal(SIGINT, handle);
+ kill(pid,SIGINT);
+ kill(pid,SIGINT);
+ kill(pid,SIGINT);
+ if (count!=3) return 1;
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+# ./__conftest || exit 1
+ ); then
+ echo 'yes'
+else
+ if (
+ $CC $CFLAGS -D__USE_BSD_SIGNAL __conftest.c -o __conftest || exit 1
+# ./__conftest || exit 1
+ ); then
+ echo '-D__USE_BSD_SIGNAL'
+ CFLAGS="$CFLAGS -D__USE_BSD_SIGNAL"
+ else
+ echo 'no'
+ echo '***WARNING***: This package needs BSD signal semantics to run.'
+ echo '***WARNING***: Assuming its just ia64 buildroot breakage.'
+ CFLAGS="$CFLAGS -D__USE_BSD_SIGNAL"
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for ncurses... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+#include <curses.h>
+#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 <<EOF >__conftest.c
+#include <stdio.h>
+#include <termcap.h>
+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 GNU libc... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+#if defined(__GLIBC__) && (__GLIBC__ >= 2)
+int tester;
+#endif
+int main() { tester=6; return 0; }
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ USE_GLIBC=1
+else
+ echo 'no'
+fi
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for libreadline... '
+if [ x$WITHOUT_READLINE != x ]; then
+ echo disabled
+else
+cat <<EOF >__conftest.c
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/tilde.h>
+int main() { readline("foo"); return 0; }
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -lreadline $LIBTERMCAP -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+ USE_READLINE=1
+ else
+ echo 'no'
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for socklen_t... '
+cat <<EOF >__conftest.c
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int main() {
+ struct sockaddr_in sn;
+ socklen_t len = sizeof(sn);
+ getpeername(0, (struct sockaddr *)&sn, &len);
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'yes'
+else
+ if (
+ $CC $CFLAGS -Dsocklen_t=int __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'int'
+ CFLAGS="$CFLAGS -Dsocklen_t=int"
+ else
+ if (
+ $CC $CFLAGS -Dsocklen_t=size_t __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'size_t'
+ CFLAGS="$CFLAGS -Dsocklen_t=size_t"
+ else
+ echo 'no'
+ echo 'Cannot work out what to use for socklen_t. Help...'
+ rm -f __conftest*
+ exit
+ fi
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+echo -n 'Checking for snprintf declaration... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+int main() {
+ void *x = (void *)snprintf;
+ printf("%lx", (long)x);
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c -o __conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'ok'
+else
+ if (
+ $CC $CFLAGS -D_GNU_SOURCE __conftest.c -o __conftest || exit 1
+# ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-D_GNU_SOURCE'
+ CFLAGS="$CFLAGS -D_GNU_SOURCE"
+ else
+ echo 'manual'
+ CFLAGS="$CFLAGS -DDECLARE_SNPRINTF"
+ fi
+fi
+rm -f __conftest*
+
+echo -n 'Checking for snprintf implementation... '
+cat <<EOF >__conftest.c
+#include <stdio.h>
+#include <string.h>
+#ifdef DECLARE_SNPRINTF
+#ifdef __cplusplus
+extern "C"
+#endif /*__cplusplus*/
+int snprintf(char *, int, const char *, ...);
+#endif /*DECLARE_SNPRINTF*/
+int main() {
+ char buf[32];
+ snprintf(buf, 8, "%s", "1234567890");
+ if (strlen(buf)!=7) return 1;
+ return 0;
+}
+
+EOF
+if (
+ $CC $CFLAGS __conftest.c $LIBBSD -o __conftest || exit 1
+# ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo 'ok'
+else
+ if (
+ $CC $CFLAGS __conftest.c -lsnprintf $LIBBSD -o __conftest || exit 1
+# ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-lsnprintf'
+ LIBS="$LIBS -lsnprintf"
+ else
+ if (
+ $CC $CFLAGS __conftest.c -ldb $LIBBSD -o __conftest || exit 1
+# ./__conftest || exit 1
+ ) >/dev/null 2>&1; then
+ echo '-ldb'
+ LIBS="$LIBS -ldb"
+ else
+ echo 'missing'
+ echo 'This package requires snprintf.'
+ rm -f __conftest*
+ exit
+ fi
+ fi
+fi
+rm -f __conftest*
+
+##################################################
+
+## libbsd should go last in case it's broken
+if [ "x$LIBBSD" != x ]; then
+ LIBS="$LIBS $LIBBSD"
+fi
+
+echo 'Generating MCONFIG...'
+(
+ echo -n '# Generated by configure (confgen version 2) on '
+ date
+ echo '#'
+ echo
+
+ echo "BINDIR=$BINDIR"
+ echo "MANDIR=$MANDIR"
+ echo "BINMODE=$BINMODE"
+ echo "MANMODE=$MANMODE"
+ echo "PREFIX=$PREFIX"
+ echo "EXECPREFIX=$EXECPREFIX"
+ echo "INSTALLROOT=$INSTALLROOT"
+ echo "CC=$CC"
+ if [ x$CC_WARNINGS != x ]; then
+ CFLAGS="$CFLAGS $WARNINGS"
+ fi
+
+ echo "CFLAGS=$CFLAGS" | sed 's/= */=/'
+ echo "LDFLAGS=$LDFLAGS" | sed 's/= */=/'
+ echo "LIBS=$LIBS" | sed 's/= */=/'
+
+ echo "LIBTERMCAP=$LIBTERMCAP"
+ echo "USE_GLIBC=$USE_GLIBC"
+ echo "USE_READLINE=$USE_READLINE"
+) > MCONFIG
+
Property changes on: create-0.17-patch/netkit-ftp-0.17-new/configure
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/Makefile
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/Makefile (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/Makefile (revision 5)
@@ -0,0 +1,30 @@
+all: ftp
+
+include ../MCONFIG
+include ../MRULES
+
+ifeq ($(USE_READLINE),1)
+CFLAGS += -D__USE_READLINE__
+LIBS += -lreadline $(LIBTERMCAP)
+endif
+
+ftp: cmds.o cmdtab.o domacro.o ftp.o glob.o main.o ruserpass.o
+ $(CC) $(LDFLAGS) $^ $(LIBS) -o $@
+
+domacro.o ftp.o glob.o main.o ruserpass.o: ftp_var.h pathnames.h
+cmds.o cmdtab.o: ftp_var.h pathnames.h cmds.h
+cmds.o glob.o: glob.h
+
+install: ftp
+ install -p -d $(INSTALLROOT)$(BINDIR)
+ install -p -m$(BINMODE) ftp $(INSTALLROOT)$(BINDIR)
+ ln -sf ftp $(INSTALLROOT)$(BINDIR)/pftp
+ install -p -d $(INSTALLROOT)$(MANDIR)/man1
+ install -p -m$(MANMODE) ftp.1 $(INSTALLROOT)$(MANDIR)/man1
+ ln -sf ftp.1 $(INSTALLROOT)$(MANDIR)/man1/pftp.1
+ install -p -d $(INSTALLROOT)$(MANDIR)/man5
+ install -p -m$(MANMODE) netrc.5 $(INSTALLROOT)$(MANDIR)/man5
+
+clean:
+ rm -f *.o ftp
+
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/cmds.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/cmds.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/cmds.c (revision 5)
@@ -0,0 +1,2380 @@
+/* $USAGI$ */
+
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * from: @(#)cmds.c 5.26 (Berkeley) 3/5/91
+ */
+char cmds_rcsid[] =
+ "$Id: cmds.c,v 1.3 2001/01/12 21:36:27 sekiya Exp $";
+
+/*
+ * FTP User Program -- Command Routines.
+ */
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <arpa/ftp.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <limits.h> /* for PATH_MAX */
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef __USE_READLINE__
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+#include "ftp_var.h"
+#include "pathnames.h"
+#include "cmds.h"
+#include "glob.h"
+
+void intr(int);
+
+extern FILE *cout;
+extern int data;
+extern const char *home;
+extern off_t restart_point;
+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 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);
+
+
+/*
+ * pipeprotect: protect against "special" local filenames by prepending
+ * "./". Special local filenames are "-" and "|..." AND "/...".
+ */
+static char *pipeprotect(char *name)
+{
+ char *nu;
+ if (strcmp(name, "-") && *name!='|' && *name!='/') {
+ return name;
+ }
+
+ /* We're going to leak this memory. XXX. */
+ nu = malloc(strlen(name)+3);
+ if (nu==NULL) {
+ perror("malloc");
+ code = -1;
+ return NULL;
+ }
+ strcpy(nu, ".");
+ if (*name != '/') strcat(nu, "/");
+ strcat(nu, name);
+ return nu;
+}
+
+/*
+ * Look for embedded ".." in a pathname and change it to "!!", printing
+ * a warning.
+ */
+static char *pathprotect(char *name)
+{
+ int gotdots=0, i, len;
+
+ /* Convert null terminator to trailing / to catch a trailing ".." */
+ len = strlen(name)+1;
+ name[len-1] = '/';
+
+ /*
+ * State machine loop. gotdots is < 0 if not looking at dots,
+ * 0 if we just saw a / and thus might start getting dots,
+ * and the count of dots seen so far if we have seen some.
+ */
+ for (i=0; i<len; i++) {
+ if (name[i]=='.' && gotdots>=0) gotdots++;
+ else if (name[i]=='/' && gotdots<0) gotdots=0;
+ else if (name[i]=='/' && gotdots==2) {
+ fprintf(stderr, "Warning: embedded .. in %.*s (changing to !!)\n",
+ len-1, name);
+ name[i-1] = '!';
+ name[i-2] = '!';
+ gotdots = 0;
+ }
+ else if (name[i]=='/') gotdots = 0;
+ else gotdots = -1;
+ }
+ name[len-1] = 0;
+ return name;
+}
+
+
+/*
+ * `Another' gets another argument, and stores the new argc and argv.
+ * It reverts to the top level (via main.c's intr()) on EOF/error.
+ *
+ * Returns false if no new arguments have been added.
+ */
+int
+another(int *pargc, char ***pargv, const char *prompt)
+{
+ int margc;
+ char **margv;
+
+ unsigned len = strlen(line);
+ int ret;
+
+ if (len >= sizeof(line) - 3) {
+ fprintf(stderr, "sorry, arguments too long\n");
+ intr(0);
+ }
+ printf("(%s) ", prompt);
+ line[len++] = ' ';
+ if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
+ intr(0);
+ len += strlen(&line[len]);
+ if (len > 0 && line[len - 1] == '\n')
+ line[len - 1] = '\0';
+ margv = makeargv(&margc, NULL);
+ ret = margc > *pargc;
+ *pargc = margc;
+ *pargv = margv;
+ return ret;
+}
+
+/*
+ * Connect to peer server and
+ * auto-login, if possible.
+ */
+void
+setpeer(int argc, char *argv[])
+{
+ char *host;
+ char *port;
+
+ if (connected) {
+ fprintf(stderr, "Already connected to %s, use close first.\n",
+ hostname);
+ code = -1;
+ return;
+ }
+ if (argc < 2)
+ (void) another(&argc, &argv, "to");
+ if (argc < 2 || argc > 3) {
+ printf("usage: %s host-name [port]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ port = NULL;
+ if (argc > 2) {
+ port = argv[2];
+ }
+ host = hookup(argv[1], port);
+ if (host) {
+ int overbose;
+
+ connected = 1;
+ try_epsv = 1;
+ try_eprt = 1;
+ /*
+ * Set up defaults for FTP.
+ */
+ (void) strcpy(typename, "ascii"), type = TYPE_A;
+ curtype = TYPE_A;
+ (void) strcpy(formname, "non-print"), form = FORM_N;
+ (void) strcpy(modename, "stream"), mode = MODE_S;
+ (void) strcpy(structname, "file"), stru = STRU_F;
+ (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))
+ fprintf(stderr,
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+ }
+ verbose = overbose;
+#else
+#warning "Unix auto-mode code skipped"
+#endif /* unix */
+ }
+}
+
+struct types {
+ const char *t_name;
+ const char *t_mode;
+ int t_type;
+ const char *t_arg;
+} types[] = {
+ { "ascii", "A", TYPE_A, NULL },
+ { "binary", "I", TYPE_I, NULL },
+ { "image", "I", TYPE_I, NULL },
+ { "ebcdic", "E", TYPE_E, NULL },
+ { "tenex", "L", TYPE_L, bytename },
+ { NULL, NULL, 0, NULL }
+};
+
+/*
+ * Set transfer type.
+ */
+static
+void
+do_settype(const char *thetype)
+{
+ struct types *p;
+ int comret;
+
+ for (p = types; p->t_name; p++)
+ if (strcmp(thetype, p->t_name) == 0)
+ break;
+ if (p->t_name == 0) {
+ fprintf(stderr, "%s: unknown mode\n", thetype);
+ code = -1;
+ return;
+ }
+ if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
+ comret = command("TYPE %s %s", p->t_mode, p->t_arg);
+ else
+ comret = command("TYPE %s", p->t_mode);
+ if (comret == COMPLETE) {
+ (void) strcpy(typename, p->t_name);
+ curtype = type = p->t_type;
+ }
+}
+
+void
+settype(int argc, char *argv[])
+{
+ struct types *p;
+ if (argc > 2) {
+ const char *sep;
+
+ printf("usage: %s [", argv[0]);
+ sep = " ";
+ for (p = types; p->t_name; p++) {
+ printf("%s%s", sep, p->t_name);
+ sep = " | ";
+ }
+ printf(" ]\n");
+ code = -1;
+ return;
+ }
+ if (argc < 2) {
+ printf("Using %s mode to transfer files.\n", typename);
+ code = 0;
+ return;
+ }
+ do_settype(argv[1]);
+}
+
+/*
+ * Internal form of settype; changes current type in use with server
+ * without changing our notion of the type for data transfers.
+ * Used to change to and from ascii for listings.
+ */
+void
+changetype(int newtype, int show)
+{
+ register struct types *p;
+ int comret, oldverbose = verbose;
+ int oldtick = tick;
+
+ if (newtype == 0)
+ newtype = TYPE_I;
+ if (newtype == curtype)
+ return;
+ if (debug == 0 && show == 0)
+ verbose = 0;
+ tick = 0;
+ for (p = types; p->t_name; p++)
+ if (newtype == p->t_type)
+ break;
+ if (p->t_name == 0) {
+ fprintf(stderr, "ftp: internal error: unknown type %d\n", newtype);
+ return;
+ }
+ if (newtype == TYPE_L && bytename[0] != '\0')
+ comret = command("TYPE %s %s", p->t_mode, bytename);
+ else
+ comret = command("TYPE %s", p->t_mode);
+ if (comret == COMPLETE)
+ curtype = newtype;
+ verbose = oldverbose;
+ tick = oldtick;
+}
+
+/*
+ * Set binary transfer type.
+ */
+/*VARARGS*/
+void
+setbinary(void)
+{
+ do_settype("binary");
+}
+
+/*
+ * Set ascii transfer type.
+ */
+/*VARARGS*/
+void
+setascii(void)
+{
+ do_settype("ascii");
+}
+
+/*
+ * Set tenex transfer type.
+ */
+/*VARARGS*/
+void
+settenex(void)
+{
+ do_settype("tenex");
+}
+
+/*
+ * Set file transfer mode.
+ */
+/*ARGSUSED*/
+void
+setmode(void)
+{
+ fprintf(stderr, "We only support %s mode, sorry.\n", modename);
+ code = -1;
+}
+
+/*
+ * Set file transfer format.
+ */
+/*ARGSUSED*/
+void
+setform(void)
+{
+ fprintf(stderr, "We only support %s format, sorry.\n", formname);
+ code = -1;
+}
+
+/*
+ * Set file transfer structure.
+ */
+void
+setstruct(void)
+{
+ fprintf(stderr, "We only support %s structure, sorry.\n", structname);
+ code = -1;
+}
+
+/*
+ * Send a single file.
+ */
+void
+put(int argc, char *argv[])
+{
+ const char *cmd;
+ int loc = 0;
+ char *oldargv1, *oldargv2;
+
+ if (argc == 2) {
+ argc++;
+ argv[2] = argv[1];
+ loc++;
+ }
+ if (argc < 2 && !another(&argc, &argv, "local-file"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "remote-file")) {
+usage:
+ printf("usage: %s local-file remote-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ oldargv1 = argv[1];
+ oldargv2 = argv[2];
+ argv[1] = globulize(argv[1]);
+ if (!argv[1]) {
+ code = -1;
+ return;
+ }
+ /*
+ * If "globulize" modifies argv[1], and argv[2] is a copy of
+ * the old argv[1], make it a copy of the new argv[1].
+ */
+ if (argv[1] != oldargv1 && argv[2] == oldargv1) {
+ argv[2] = argv[1];
+ }
+ cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
+ if (loc && ntflag) {
+ argv[2] = dotrans(argv[2]);
+ }
+ if (loc && mapflag) {
+ argv[2] = domap(argv[2]);
+ }
+ sendrequest(cmd, argv[1], argv[2],
+ argv[1] != oldargv1 || argv[2] != oldargv2);
+ if (argv[1] != oldargv1) {
+ free(argv[1]);
+ }
+}
+
+void mabort(int);
+
+/*
+ * Send multiple files.
+ */
+void
+mput(int argc, char *argv[])
+{
+ register int i;
+ void (*oldintr)(int);
+ int ointer;
+ char *tp;
+
+ if (argc < 2 && !another(&argc, &argv, "local-files")) {
+ printf("usage: %s local-files\n", argv[0]);
+ code = -1;
+ return;
+ }
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT, mabort);
+ (void) sigsetjmp(jabort, 1);
+ if (proxy) {
+ char *cp, *tp2, tmpbuf[PATH_MAX];
+
+ while ((cp = remglob(argv,0)) != NULL) {
+ if (*cp == 0) {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ tp = cp;
+ if (mcase) {
+ while (*tp && !islower(*tp)) {
+ tp++;
+ }
+ if (!*tp) {
+ tp = cp;
+ tp2 = tmpbuf;
+ while ((*tp2 = *tp) != '\0') {
+ if (isupper(*tp2)) {
+ *tp2 = 'a' + *tp2 - 'A';
+ }
+ tp++;
+ tp2++;
+ }
+ }
+ tp = tmpbuf;
+ }
+ if (ntflag) {
+ tp = dotrans(tp);
+ }
+ if (mapflag) {
+ tp = domap(tp);
+ }
+ sendrequest((sunique) ? "STOU" : "STOR",
+ cp, tp, cp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ (void) signal(SIGINT, oldintr);
+ mflag = 0;
+ return;
+ }
+ for (i = 1; i < argc; i++) {
+ register char **cpp, **gargs;
+
+ if (!doglob) {
+ if (mflag && confirm(argv[0], argv[i])) {
+ tp = (ntflag) ? dotrans(argv[i]) : argv[i];
+ tp = (mapflag) ? domap(tp) : tp;
+ sendrequest((sunique) ? "STOU" : "STOR",
+ argv[i], tp, tp != argv[i] || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ continue;
+ }
+ gargs = ftpglob(argv[i]);
+ if (globerr != NULL) {
+ fprintf(stderr, "%s\n", globerr);
+ if (gargs) {
+ blkfree(gargs);
+ free((char *)gargs);
+ }
+ continue;
+ }
+ for (cpp = gargs; cpp && *cpp != NULL; cpp++) {
+ if (mflag && confirm(argv[0], *cpp)) {
+ tp = (ntflag) ? dotrans(*cpp) : *cpp;
+ tp = (mapflag) ? domap(tp) : tp;
+ sendrequest((sunique) ? "STOU" : "STOR",
+ *cpp, tp, *cpp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ if (gargs != NULL) {
+ blkfree(gargs);
+ free((char *)gargs);
+ }
+ }
+ (void) signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+void
+reget(int argc, char *argv[])
+{
+ (void) getit(argc, argv, 1, "r+w");
+}
+
+void
+get(int argc, char *argv[])
+{
+ (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );
+}
+
+/*
+ * Receive one file.
+ */
+static int
+getit(int argc, char *argv[], int restartit, const char *modestr)
+{
+ int loc = 0;
+ char *oldargv1, *oldargv2;
+
+ if (argc == 2) {
+ argc++;
+ /*
+ * Protect the user from accidentally retrieving special
+ * local names.
+ */
+ argv[2] = pipeprotect(argv[1]);
+ if (!argv[2]) {
+ code = -1;
+ return 0;
+ }
+ loc++;
+ }
+ if (argc < 2 && !another(&argc, &argv, "remote-file"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+ printf("usage: %s remote-file [ local-file ]\n", argv[0]);
+ code = -1;
+ return (0);
+ }
+ oldargv1 = argv[1];
+ oldargv2 = argv[2];
+ argv[2] = globulize(argv[2]);
+ if (!argv[2]) {
+ code = -1;
+ return (0);
+ }
+ if (loc && mcase) {
+ char *tp = argv[1], *tp2, tmpbuf[PATH_MAX];
+
+ while (*tp && !islower(*tp)) {
+ tp++;
+ }
+ if (!*tp) {
+ tp = argv[2];
+ tp2 = tmpbuf;
+ while ((*tp2 = *tp) != '\0') {
+ if (isupper(*tp2)) {
+ *tp2 = 'a' + *tp2 - 'A';
+ }
+ tp++;
+ tp2++;
+ }
+ argv[2] = tmpbuf;
+ }
+ }
+ if (loc && ntflag)
+ argv[2] = dotrans(argv[2]);
+ if (loc && mapflag)
+ argv[2] = domap(argv[2]);
+ if (restartit) {
+ struct stat stbuf;
+ int ret;
+
+ ret = stat(argv[2], &stbuf);
+ if (restartit == 1) {
+ if (ret < 0) {
+ fprintf(stderr, "local: %s: %s\n", argv[2],
+ strerror(errno));
+ return (0);
+ }
+ restart_point = stbuf.st_size;
+ } else {
+ if (ret == 0) {
+ int overbose;
+
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ if (command("MDTM %s", argv[1]) == COMPLETE) {
+ int yy, mo, day, hour, min, sec;
+ struct tm *tm;
+ verbose = overbose;
+ sscanf(reply_string,
+ "%*s %04d%02d%02d%02d%02d%02d",
+ &yy, &mo, &day, &hour, &min, &sec);
+ tm = gmtime(&stbuf.st_mtime);
+ tm->tm_mon++;
+/* Indentation is misleading, but changes keep small. */
+/*
+ * I think the indentation and braces are now correct. Whoever put this
+ * in the way it was originally should be prohibited by law.
+ */
+ if (tm->tm_year+1900 > yy)
+ return (1);
+ if (tm->tm_year+1900 == yy) {
+ if (tm->tm_mon > mo)
+ return (1);
+ if (tm->tm_mon == mo) {
+ if (tm->tm_mday > day)
+ return (1);
+ if (tm->tm_mday == day) {
+ if (tm->tm_hour > hour)
+ return (1);
+ if (tm->tm_hour == hour) {
+ if (tm->tm_min > min)
+ return (1);
+ if (tm->tm_min == min) {
+ if (tm->tm_sec > sec)
+ return (1);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ printf("%s\n", reply_string);
+ verbose = overbose;
+ return (0);
+ }
+ }
+ }
+ }
+
+ recvrequest("RETR", argv[2], argv[1], modestr,
+ argv[1] != oldargv1 || argv[2] != oldargv2);
+ (void) close(data), data = -1;
+ restart_point = 0;
+ return (0);
+}
+
+void
+mabort(int ignore)
+{
+ int ointer;
+
+ (void)ignore;
+
+ printf("\n");
+ (void) fflush(stdout);
+ if (mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", mname)) {
+ interactive = ointer;
+ siglongjmp(jabort,0);
+ }
+ interactive = ointer;
+ }
+ mflag = 0;
+ siglongjmp(jabort,0);
+}
+
+/*
+ * Get multiple files.
+ */
+void
+mget(int argc, char **argv)
+{
+ void (*oldintr)(int);
+ int ointer;
+ char *cp, *tp, *tp2, tmpbuf[PATH_MAX];
+
+ if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+ printf("usage: %s remote-files\n", argv[0]);
+ code = -1;
+ return;
+ }
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT,mabort);
+ (void) sigsetjmp(jabort, 1);
+ while ((cp = remglob(argv,proxy)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ tp = cp;
+ if (mcase) {
+ while (*tp && !islower(*tp)) {
+ tp++;
+ }
+ if (!*tp) {
+ tp = cp;
+ tp2 = tmpbuf;
+ while ((*tp2 = *tp) != '\0') {
+ if (isupper(*tp2)) {
+ *tp2 = 'a' + *tp2 - 'A';
+ }
+ tp++;
+ tp2++;
+ }
+ tp = tmpbuf;
+ }
+ else {
+ tp = cp;
+ }
+ }
+ if (ntflag) {
+ tp = dotrans(tp);
+ }
+ if (mapflag) {
+ tp = domap(tp);
+ }
+ /* Reject embedded ".." */
+ tp = pathprotect(tp);
+
+ /* 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);
+ }
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mget")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ (void) signal(SIGINT,oldintr);
+ mflag = 0;
+}
+
+char *
+remglob(char *argv[], int doswitch)
+{
+ char temp[16];
+ static char buf[PATH_MAX];
+ static FILE *ftemp = NULL;
+ static char **args;
+ int oldverbose, oldhash, badglob = 0;
+ char *cp;
+
+ if (!mflag) {
+ if (!doglob) {
+ args = NULL;
+ }
+ else {
+ if (ftemp) {
+ (void) fclose(ftemp);
+ ftemp = NULL;
+ }
+ }
+ return(NULL);
+ }
+ if (!doglob) {
+ if (args == NULL)
+ args = argv;
+ if ((cp = *++args) == NULL)
+ args = NULL;
+ return (cp);
+ }
+ if (ftemp == NULL) {
+ int oldumask, fd;
+ (void) strcpy(temp, _PATH_TMP);
+
+ /* libc 5.2.18 creates with mode 0666, which is dumb */
+ oldumask = umask(077);
+ fd = mkstemp(temp);
+ umask(oldumask);
+
+ if (fd<0) {
+ fprintf(stderr, "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);
+
+ recvrequest ("NLST", temp, *argv, "a", 0);
+ if (!checkglob(dupfd, *argv)) {
+ badglob = 1;
+ break;
+ }
+ }
+ unlink(temp);
+
+ if (doswitch) {
+ pswitch(!proxy);
+ }
+ verbose = oldverbose; hash = oldhash;
+ if (badglob) {
+ fprintf(stderr, "Refusing to handle insecure file list\n");
+ close(fd);
+ return NULL;
+ }
+ ftemp = fdopen(fd, "r");
+ if (ftemp == NULL) {
+ fprintf(stderr, "fdopen failed, oops\n");
+ return NULL;
+ }
+ rewind(ftemp);
+ }
+ if (fgets(buf, sizeof (buf), ftemp) == NULL) {
+ (void) fclose(ftemp), ftemp = NULL;
+ return (NULL);
+ }
+ if ((cp = index(buf, '\n')) != NULL)
+ *cp = '\0';
+ return (buf);
+}
+
+/*
+ * Check whether given pattern matches `..'
+ * We assume only a glob pattern starting with a dot will match
+ * dot entries on the server.
+ */
+static int
+isdotdotglob(const char *pattern)
+{
+ int havedot = 0;
+ char c;
+
+ if (*pattern++ != '.')
+ return 0;
+ while ((c = *pattern++) != '\0' && c != '/') {
+ if (c == '*' || c == '?')
+ continue;
+ if (c == '.' && havedot++)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * This function makes sure the list of globbed files returned from
+ * the server doesn't contain anything dangerous such as
+ * /home/<yourname>/.forward, or ../.forward,
+ * or |mail foe@doe </etc/passwd, etc.
+ * Covered areas:
+ * - returned name starts with / but glob pattern doesn't
+ * - glob pattern starts with / but returned name doesn't
+ * - returned name starts with |
+ * - returned name contains .. in a position where glob
+ * pattern doesn't match ..
+ * I.e. foo/.* allows foo/../bar but not foo/.bar/../fly
+ *
+ * Note that globbed names starting with / should really be stored
+ * under the current working directory; this is handled in mget above.
+ * --okir
+ */
+static int
+checkglob(int fd, 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 `..'
+ */
+ initial = (pattern[0] == '/');
+ for (sp = pattern, nrslash = 0; sp != 0; sp = strchr(sp, '/')) {
+ while (*sp == '/')
+ sp++;
+ if (nrslash >= MAXPATHLEN) {
+ fprintf(stderr, "Incredible pattern: %s\n", pattern);
+ return 0;
+ }
+ dotdot[nrslash++] = isdotdotglob(sp);
+ }
+
+ fp = fdopen(fd, "r");
+ while (okay && fgets(buffer, sizeof(buffer), fp) != NULL) {
+ char *sp;
+
+ if ((sp = strchr(buffer, '\n')) != 0) {
+ *sp = '\0';
+ } else {
+ fprintf(stderr, "Extremely long filename from server: %s",
+ buffer);
+ okay = 0;
+ break;
+ }
+ if (buffer[0] == '|'
+ || (buffer[0] != '/' && initial)
+ || (buffer[0] == '/' && !initial))
+ okay = 0;
+ for (sp = buffer, nr = 0; sp; sp = strchr(sp, '/'), nr++) {
+ while (*sp == '/')
+ sp++;
+ if (sp[0] == '.' && !strncmp(sp, "../", 3)
+ && (nr >= nrslash || !dotdot[nr]))
+ okay = 0;
+ }
+ }
+
+ if (!okay)
+ fprintf(stderr, "Filename provided by server "
+ "doesn't match pattern `%s': %s\n", pattern, buffer);
+
+ fclose(fp);
+ return okay;
+}
+
+static const char *
+onoff(int bool)
+{
+ return (bool ? "on" : "off");
+}
+
+/*
+ * Show status.
+ */
+void
+status(void)
+{
+ int i;
+ if (connected)
+ printf("Connected to %s.\n", hostname);
+ else
+ fprintf(stderr, "Not connected.\n");
+ if (!proxy) {
+ pswitch(1);
+ if (connected) {
+ printf("Connected for proxy commands to %s.\n", hostname);
+ }
+ else {
+ fprintf(stderr, "No proxy connection.\n");
+ }
+ pswitch(0);
+ }
+ printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
+ modename, typename, formname, structname);
+ printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
+ onoff(verbose), onoff(bell), onoff(interactive),
+ onoff(doglob));
+ printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
+ onoff(runique));
+ printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag));
+ if (ntflag) {
+ printf("Ntrans: (in) %s (out) %s\n",ntin,ntout);
+ }
+ else {
+ printf("Ntrans: off\n");
+ }
+ if (mapflag) {
+ printf("Nmap: (in) %s (out) %s\n", mapin, mapout);
+ }
+ else {
+ printf("Nmap: off\n");
+ }
+ printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
+ onoff(hash), onoff(sendport));
+ printf("Tick counter printing: %s\n", onoff(tick));
+ if (macnum > 0) {
+ printf("Macros:\n");
+ for (i=0; i<macnum; i++) {
+ printf("\t%s\n",macros[i].mac_name);
+ }
+ }
+ code = 0;
+}
+
+/*
+ * Set beep on cmd completed mode.
+ */
+void
+setbell(void)
+{
+
+ bell = !bell;
+ printf("Bell mode %s.\n", onoff(bell));
+ code = bell;
+}
+
+/*
+ * Turn on packet tracing.
+ */
+void
+settrace(void)
+{
+ traceflag = !traceflag;
+ printf("Packet tracing %s.\n", onoff(traceflag));
+ code = traceflag;
+}
+
+/*
+ * Toggle hash mark printing during transfers.
+ */
+void
+sethash(void)
+{
+ hash = !hash;
+ if (hash && tick)
+ settick();
+
+ printf("Hash mark printing %s", onoff(hash));
+ code = hash;
+ if (hash)
+ printf(" (%d bytes/hash mark)", 1024);
+ printf(".\n");
+}
+
+/*
+ * Toggle tick counter printing during transfers.
+ */
+void
+settick(void)
+{
+ tick = !tick;
+ if (hash && tick)
+ sethash();
+ printf("Tick counter printing %s", onoff(tick));
+ code = tick;
+ if (tick)
+ printf(" (%d bytes/tick increment)", TICKBYTES);
+ printf(".\n");
+}
+
+/*
+ * Turn on printing of server echos.
+ */
+void
+setverbose(void)
+{
+ verbose = !verbose;
+ printf("Verbose mode %s.\n", onoff(verbose));
+ code = verbose;
+}
+
+/*
+ * Toggle PORT cmd use before each data connection.
+ */
+void
+setport(void)
+{
+ sendport = !sendport;
+ printf("Use of PORT cmds %s.\n", onoff(sendport));
+ code = sendport;
+}
+
+/*
+ * Turn on interactive prompting
+ * during mget, mput, and mdelete.
+ */
+void
+setprompt(void)
+{
+ interactive = !interactive;
+ printf("Interactive mode %s.\n", onoff(interactive));
+ code = interactive;
+}
+
+/*
+ * Toggle metacharacter interpretation
+ * on local file names.
+ */
+void
+setglob(void)
+{
+ doglob = !doglob;
+ printf("Globbing %s.\n", onoff(doglob));
+ code = doglob;
+}
+
+/*
+ * Set debugging mode on/off and/or
+ * set level of debugging.
+ */
+void
+setdebug(int argc, char *argv[])
+{
+ int val;
+
+ if (argc > 1) {
+ val = atoi(argv[1]);
+ if (val < 0) {
+ fprintf(stderr, "%s: bad debugging value.\n", argv[1]);
+ code = -1;
+ return;
+ }
+ } else
+ val = !debug;
+ debug = val;
+ if (debug)
+ options |= SO_DEBUG;
+ else
+ options &= ~SO_DEBUG;
+ printf("Debugging %s (debug=%d).\n", onoff(debug), debug);
+ code = debug > 0;
+}
+
+/*
+ * Set current working directory
+ * on remote machine.
+ */
+void
+cd(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "remote-directory")) {
+ printf("usage: %s remote-directory\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("CWD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ fprintf(stderr, "CWD command not recognized, trying XCWD\n");
+ (void) command("XCWD %s", argv[1]);
+ }
+}
+
+/*
+ * Set current working directory
+ * on local machine.
+ */
+void
+lcd(int argc, char *argv[])
+{
+ char buf[PATH_MAX];
+ const char *dir = NULL;
+
+ if (argc == 1) {
+ /*dir = home;*/
+ dir = ".";
+ }
+ else if (argc != 2) {
+ printf("usage: %s local-directory\n", argv[0]);
+ code = -1;
+ return;
+ }
+ else {
+ dir = globulize(argv[1]);
+ }
+ if (!dir) {
+ code = -1;
+ return;
+ }
+ if (chdir(dir) < 0) {
+ fprintf(stderr, "local: %s: %s\n", dir, strerror(errno));
+ code = -1;
+ return;
+ }
+ if (!getcwd(buf, sizeof(buf))) {
+ if (errno==ERANGE) strcpy(buf, "<too long>");
+ else strcpy(buf, "???");
+ }
+ printf("Local directory now %s\n", buf);
+ code = 0;
+}
+
+/*
+ * Delete a single file.
+ */
+void
+delete_cmd(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+ printf("usage: %s remote-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ (void) command("DELE %s", argv[1]);
+}
+
+/*
+ * Delete multiple files.
+ */
+void
+mdelete(int argc, char *argv[])
+{
+ void (*oldintr)(int);
+ int ointer;
+ char *cp;
+
+ if (argc < 2 && !another(&argc, &argv, "remote-files")) {
+ printf("usage: %s remote-files\n", argv[0]);
+ code = -1;
+ return;
+ }
+ mname = argv[0];
+ mflag = 1;
+ oldintr = signal(SIGINT, mabort);
+ (void) sigsetjmp(jabort, 1);
+ while ((cp = remglob(argv,0)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ (void) command("DELE %s", cp);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", "mdelete")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ (void) signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+/*
+ * Rename a remote file.
+ */
+void
+renamefile(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "from-name"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "to-name")) {
+usage:
+ printf("%s from-name to-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("RNFR %s", argv[1]) == CONTINUE)
+ (void) command("RNTO %s", argv[2]);
+}
+
+/*
+ * Get a directory listing
+ * of remote files.
+ */
+void
+ls(int argc, char *argv[])
+{
+ static char foo[2] = "-";
+ const char *cmd;
+
+ if (argc < 2) {
+ argc++, argv[1] = NULL;
+ }
+ if (argc < 3) {
+ argc++, argv[2] = foo;
+ }
+ if (argc > 3) {
+ printf("usage: %s remote-directory local-file\n", argv[0]);
+ 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 ||
+ !confirm("output to local-file:", argv[2])) {
+ code = -1;
+ return;
+ }
+ recvrequest(cmd, argv[2], argv[1], "w", 0);
+}
+
+/*
+ * Get a directory listing
+ * of multiple remote files.
+ */
+void
+mls(int argc, char *argv[])
+{
+ void (*oldintr)(int);
+ int ointer, i;
+ const char *volatile cmd;
+ char *volatile dest;
+ const char *modestr;
+
+ if (argc < 2 && !another(&argc, &argv, "remote-files"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "local-file")) {
+usage:
+ printf("usage: %s remote-files local-file\n", argv[0]);
+ 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)) {
+ 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);
+
+ for (i = 1; mflag && i < argc-1; ++i) {
+ modestr = (i == 1) ? "w" : "a";
+ recvrequest(cmd, dest, argv[i], modestr, 0);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", argv[0])) {
+ mflag ++;
+ }
+ interactive = ointer;
+ }
+ }
+ (void) signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+/*
+ * Do a shell escape
+ */
+void
+shell(const char *arg)
+{
+ int pid;
+ void (*old1)(int);
+ void (*old2)(int);
+ char shellnam[40];
+ const char *theshell, *namep;
+
+ old1 = signal (SIGINT, SIG_IGN);
+ old2 = signal (SIGQUIT, SIG_IGN);
+ if ((pid = fork()) == 0) {
+ for (pid = 3; pid < 20; pid++)
+ (void) close(pid);
+ (void) signal(SIGINT, SIG_DFL);
+ (void) signal(SIGQUIT, SIG_DFL);
+ theshell = getenv("SHELL");
+ if (theshell == NULL)
+ theshell = _PATH_BSHELL;
+ namep = strrchr(theshell, '/');
+ if (namep == NULL)
+ namep = theshell;
+ else
+ namep++;
+ (void) strcpy(shellnam,"-");
+ (void) strcat(shellnam, namep);
+ if (strcmp(namep, "sh") != 0)
+ shellnam[0] = '+';
+ if (debug) {
+ printf("%s\n", theshell);
+ (void) fflush (stdout);
+ }
+ if (arg) {
+ execl(theshell, shellnam, "-c", arg, NULL);
+ }
+ else {
+ execl(theshell, shellnam, NULL);
+ }
+ perror(theshell);
+ code = -1;
+ exit(1);
+ }
+ if (pid > 0) while (wait(NULL) != pid);
+
+ (void) signal(SIGINT, old1);
+ (void) signal(SIGQUIT, old2);
+ if (pid == -1) {
+ perror("Try again later");
+ code = -1;
+ }
+ else {
+ code = 0;
+ }
+}
+
+/*
+ * Send new user information (re-login)
+ */
+void
+user(int argc, char *argv[])
+{
+ char theacct[80];
+ int n, aflag = 0;
+
+ if (argc < 2)
+ (void) another(&argc, &argv, "username");
+ if (argc < 2 || argc > 4) {
+ printf("usage: %s username [password] [account]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ n = command("USER %s", argv[1]);
+ if (n == CONTINUE) {
+ if (argc < 3 )
+ argv[2] = getpass("Password: "), argc++;
+ n = command("PASS %s", argv[2]);
+ }
+ if (n == CONTINUE) {
+ if (argc < 4) {
+ printf("Account: "); (void) fflush(stdout);
+ fgets(theacct, sizeof(theacct), stdin);
+ argv[3] = theacct; argc++;
+ }
+ n = command("ACCT %s", argv[3]);
+ aflag++;
+ }
+ if (n != COMPLETE) {
+ fprintf(stderr, "Login failed.\n");
+ return;
+ }
+ if (!aflag && argc == 4) {
+ (void) command("ACCT %s", argv[3]);
+ }
+}
+
+/*
+ * Print working directory.
+ */
+void
+pwd(void)
+{
+ int oldverbose = verbose;
+
+ /*
+ * If we aren't verbose, this doesn't do anything!
+ */
+ verbose = 1;
+ if (command("PWD") == ERROR && code == 500) {
+ fprintf(stderr, "PWD command not recognized, trying XPWD\n");
+ (void) command("XPWD");
+ }
+ verbose = oldverbose;
+}
+
+/*
+ * Make a directory.
+ */
+void
+makedir(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+ printf("usage: %s directory-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("MKD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ fprintf(stderr, "MKD command not recognized, trying XMKD\n");
+ (void) command("XMKD %s", argv[1]);
+ }
+}
+
+/*
+ * Remove a directory.
+ */
+void
+removedir(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "directory-name")) {
+ printf("usage: %s directory-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (command("RMD %s", argv[1]) == ERROR && code == 500) {
+ if (verbose)
+ fprintf(stderr, "RMD command not recognized, trying XRMD\n");
+ (void) command("XRMD %s", argv[1]);
+ }
+}
+
+/*
+ * Send a line, verbatim, to the remote machine.
+ */
+void
+quote(int argc, char *argv[])
+{
+ if (argc < 2 && !another(&argc, &argv, "command line to send")) {
+ printf("usage: %s line-to-send\n", argv[0]);
+ code = -1;
+ return;
+ }
+ quote1("", argc, argv);
+}
+
+/*
+ * Send a SITE command to the remote machine. The line
+ * is sent verbatim to the remote machine, except that the
+ * word "SITE" is added at the front.
+ */
+void
+site(int argc, char *argv[])
+{
+ if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
+ printf("usage: %s line-to-send\n", argv[0]);
+ code = -1;
+ return;
+ }
+ quote1("SITE ", argc, argv);
+}
+
+/*
+ * Turn argv[1..argc) into a space-separated string, then prepend initial text.
+ * Send the result as a one-line command and get response.
+ */
+static void
+quote1(const char *initial, int argc, char **argv)
+{
+ register int i, len;
+ char buf[BUFSIZ]; /* must be >= sizeof(line) */
+
+ if (strncmp(argv[1],"size",4) == 0)
+ changetype(TYPE_I, 1);
+ (void) strcpy(buf, initial);
+ if (argc > 1) {
+ len = strlen(buf);
+ len += strlen(strcpy(&buf[len], argv[1]));
+ for (i = 2; i < argc; i++) {
+ buf[len++] = ' ';
+ len += strlen(strcpy(&buf[len], argv[i]));
+ }
+ }
+ if (command("%s", buf) == PRELIM) {
+ while (getreply(0) == PRELIM);
+ }
+}
+
+void
+do_chmod(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "mode"))
+ goto usage;
+ if (argc < 3 && !another(&argc, &argv, "file-name")) {
+usage:
+ printf("usage: %s mode file-name\n", argv[0]);
+ code = -1;
+ return;
+ }
+ (void) command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void
+do_umask(int argc, char *argv[])
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+ verbose = oldverbose;
+}
+
+void
+idle_cmd(int argc, char *argv[])
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
+ verbose = oldverbose;
+}
+
+/*
+ * Ask the other side for help.
+ */
+void
+rmthelp(int argc, char *argv[])
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
+ verbose = oldverbose;
+}
+
+/*
+ * Terminate session and exit.
+ */
+void
+quit(void)
+{
+
+ if (connected)
+ disconnect();
+ pswitch(1);
+ if (connected) {
+ disconnect();
+ }
+ exit(0);
+}
+
+/*
+ * Terminate session, but don't exit.
+ */
+void
+disconnect(void)
+{
+ if (!connected)
+ return;
+ (void) command("QUIT");
+ if (cout) {
+ (void) fclose(cout);
+ }
+ cout = NULL;
+ connected = 0;
+ data = -1;
+ if (!proxy) {
+ macnum = 0;
+ }
+}
+
+static int
+confirm(const char *cmd, const char *file)
+{
+ char lyne[BUFSIZ];
+
+ if (!interactive)
+ return (1);
+
+#ifdef __USE_READLINE__
+ if (fromatty && !rl_inhibit) {
+ char *lineread;
+ snprintf(lyne, BUFSIZ, "%s %s? ", cmd, file);
+ lineread = readline(lyne);
+ if (!lineread) return 0;
+ strcpy(lyne, lineread);
+ free(lineread);
+ }
+ else {
+#endif
+ printf("%s %s? ", cmd, file);
+ fflush(stdout);
+ if (fgets(lyne, sizeof(lyne), stdin) == NULL) {
+ return 0;
+ }
+#ifdef __USE_READLINE__
+ }
+#endif
+ return (*lyne != 'n' && *lyne != 'N');
+}
+
+void
+fatal(const char *msg)
+{
+
+ fprintf(stderr, "ftp: %s\n", msg);
+ exit(1);
+}
+
+/*
+ * Glob a local file name specification with
+ * the expectation of a single return value.
+ * Can't control multiple values being expanded
+ * from the expression, we return only the first.
+ */
+static
+char *
+globulize(char *cpp)
+{
+ char **globbed;
+ char *rv = cpp;
+
+ if (!doglob) return cpp;
+
+ globbed = ftpglob(cpp);
+ if (globerr != NULL) {
+ printf("%s: %s\n", cpp, globerr);
+ if (globbed) {
+ blkfree(globbed);
+ free(globbed);
+ }
+ return NULL;
+ }
+ if (globbed) {
+ rv = globbed[0];
+ /* don't waste too much memory */
+ if (globbed[0]) {
+ blkfree(globbed+1);
+ }
+ free(globbed);
+ }
+ return rv;
+}
+
+void
+account(int argc, char *argv[])
+{
+ char buf[128], *ap;
+
+ if (argc > 1) {
+ *buf = 0;
+ while (argc > 1) {
+ --argc;
+ ++argv;
+ strncat(buf, *argv, sizeof(buf)-strlen(buf)-1);
+ }
+ ap = buf;
+ }
+ else {
+ ap = getpass("Account:");
+ }
+ command("ACCT %s", ap);
+}
+
+static
+void
+proxabort(int ignore)
+{
+ (void)ignore;
+
+ if (!proxy) {
+ pswitch(1);
+ }
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ siglongjmp(abortprox,1);
+}
+
+void
+doproxy(int argc, char *argv[])
+{
+ register struct cmd *c;
+ void (*oldintr)(int);
+
+ if (argc < 2 && !another(&argc, &argv, "command")) {
+ printf("usage: %s command\n", argv[0]);
+ code = -1;
+ return;
+ }
+ c = getcmd(argv[1]);
+ if (c == (struct cmd *) -1) {
+ printf("?Ambiguous command\n");
+ (void) fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ (void) fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (!c->c_proxy) {
+ printf("?Invalid proxy command\n");
+ (void) fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (sigsetjmp(abortprox, 1)) {
+ code = -1;
+ return;
+ }
+ oldintr = signal(SIGINT, proxabort);
+ pswitch(1);
+ if (c->c_conn && !connected) {
+ printf("Not connected\n");
+ (void) fflush(stdout);
+ pswitch(0);
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+
+ if (c->c_handler_v) c->c_handler_v(argc-1, argv+1);
+ else if (c->c_handler_0) c->c_handler_0();
+ else c->c_handler_1(NULL); /* should not reach this */
+
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ (void) signal(SIGINT, oldintr);
+}
+
+void
+setcase(void)
+{
+ mcase = !mcase;
+ printf("Case mapping %s.\n", onoff(mcase));
+ code = mcase;
+}
+
+void
+setcr(void)
+{
+ crflag = !crflag;
+ printf("Carriage Return stripping %s.\n", onoff(crflag));
+ code = crflag;
+}
+
+void
+setntrans(int argc, char *argv[])
+{
+ if (argc == 1) {
+ ntflag = 0;
+ printf("Ntrans off.\n");
+ code = ntflag;
+ return;
+ }
+ ntflag++;
+ code = ntflag;
+ (void) strncpy(ntin, argv[1], NTRANS_MAX);
+ ntin[NTRANS_MAX] = '\0';
+ if (argc == 2) {
+ ntout[0] = '\0';
+ return;
+ }
+ (void) strncpy(ntout, argv[2], NTRANS_MAX);
+ ntout[NTRANS_MAX] = '\0';
+}
+
+static char *
+dotrans(char *name)
+{
+ static char new[PATH_MAX];
+ char *cp1, *cp2 = new;
+ register int i, ostop, found;
+
+ for (ostop = 0; *(ntout + ostop) && ostop < NTRANS_MAX; ostop++);
+ for (cp1 = name; *cp1; cp1++) {
+ found = 0;
+ for (i = 0; *(ntin + i) && i < NTRANS_MAX; i++) {
+ if (*cp1 == *(ntin + i)) {
+ found++;
+ if (i < ostop) {
+ *cp2++ = *(ntout + i);
+ }
+ break;
+ }
+ }
+ if (!found) {
+ *cp2++ = *cp1;
+ }
+ }
+ *cp2 = '\0';
+ return(new);
+}
+
+void
+setnmap(int argc, char *argv[])
+{
+ char *cp;
+
+ if (argc == 1) {
+ mapflag = 0;
+ printf("Nmap off.\n");
+ code = mapflag;
+ return;
+ }
+ if (argc < 3 && !another(&argc, &argv, "mapout")) {
+ printf("Usage: %s [mapin mapout]\n",argv[0]);
+ code = -1;
+ return;
+ }
+ mapflag = 1;
+ code = 1;
+ cp = index(altarg, ' ');
+ if (proxy) {
+ while(*++cp == ' ');
+ altarg = cp;
+ cp = index(altarg, ' ');
+ }
+ *cp = '\0';
+ (void) strncpy(mapin, altarg, PATH_MAX - 1);
+ mapin[PATH_MAX-1] = 0;
+ while (*++cp == ' ');
+ (void) strncpy(mapout, cp, PATH_MAX - 1);
+ mapout[PATH_MAX-1] = 0;
+}
+
+static
+char *
+domap(char *name)
+{
+ static char new[PATH_MAX];
+ register char *cp1 = name, *cp2 = mapin;
+ char *tp[9], *te[9];
+ int i, toks[9], toknum = 0, match = 1;
+
+ for (i=0; i < 9; ++i) {
+ toks[i] = 0;
+ }
+ while (match && *cp1 && *cp2) {
+ switch (*cp2) {
+ case '\\':
+ if (*++cp2 != *cp1) {
+ match = 0;
+ }
+ break;
+ case '$':
+ if (*(cp2+1) >= '1' && *(cp2+1) <= '9') {
+ if (*cp1 != *(++cp2+1)) {
+ toknum = *cp2 - '1';
+ toks[toknum]++;
+ tp[toknum] = cp1;
+ while (*++cp1 && *(cp2+1)
+ != *cp1);
+ te[toknum] = cp1;
+ }
+ cp2++;
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (*cp2 != *cp1) {
+ match = 0;
+ }
+ break;
+ }
+ if (match && *cp1) {
+ cp1++;
+ }
+ if (match && *cp2) {
+ cp2++;
+ }
+ }
+ if (!match && *cp1) /* last token mismatch */
+ {
+ toks[toknum] = 0;
+ }
+ cp1 = new;
+ *cp1 = '\0';
+ cp2 = mapout;
+ while (*cp2) {
+ match = 0;
+ switch (*cp2) {
+ case '\\':
+ if (*(cp2 + 1)) {
+ *cp1++ = *++cp2;
+ }
+ break;
+ case '[':
+LOOP:
+ if (*++cp2 == '$' && isdigit(*(cp2+1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ match = 1;
+ }
+ else if (toks[toknum = *cp2 - '1']) {
+ char *cp3 = tp[toknum];
+
+ while (cp3 != te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ match = 1;
+ }
+ }
+ else {
+ while (*cp2 && *cp2 != ',' &&
+ *cp2 != ']') {
+ if (*cp2 == '\\') {
+ cp2++;
+ }
+ else if (*cp2 == '$' &&
+ isdigit(*(cp2+1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ }
+ else if (toks[toknum =
+ *cp2 - '1']) {
+ char *cp3=tp[toknum];
+
+ while (cp3 !=
+ te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ }
+ }
+ else if (*cp2) {
+ *cp1++ = *cp2++;
+ }
+ }
+ if (!*cp2) {
+ printf("nmap: unbalanced brackets\n");
+ return(name);
+ }
+ match = 1;
+ cp2--;
+ }
+ if (match) {
+ while (*++cp2 && *cp2 != ']') {
+ if (*cp2 == '\\' && *(cp2 + 1)) {
+ cp2++;
+ }
+ }
+ if (!*cp2) {
+ printf("nmap: unbalanced brackets\n");
+ return(name);
+ }
+ break;
+ }
+ switch (*++cp2) {
+ case ',':
+ goto LOOP;
+ case ']':
+ break;
+ default:
+ cp2--;
+ goto LOOP;
+ }
+ break;
+ case '$':
+ if (isdigit(*(cp2 + 1))) {
+ if (*++cp2 == '0') {
+ char *cp3 = name;
+
+ while (*cp3) {
+ *cp1++ = *cp3++;
+ }
+ }
+ else if (toks[toknum = *cp2 - '1']) {
+ char *cp3 = tp[toknum];
+
+ while (cp3 != te[toknum]) {
+ *cp1++ = *cp3++;
+ }
+ }
+ break;
+ }
+ /* intentional drop through */
+ default:
+ *cp1++ = *cp2;
+ break;
+ }
+ cp2++;
+ }
+ *cp1 = '\0';
+ if (!*new) {
+ return(name);
+ }
+ return(new);
+}
+
+void
+setsunique(void)
+{
+ sunique = !sunique;
+ printf("Store unique %s.\n", onoff(sunique));
+ code = sunique;
+}
+
+void
+setrunique(void)
+{
+ runique = !runique;
+ printf("Receive unique %s.\n", onoff(runique));
+ code = runique;
+}
+
+/* change directory to parent directory */
+void
+cdup(void)
+{
+ if (command("CDUP") == ERROR && code == 500) {
+ if (verbose)
+ fprintf(stderr, "CDUP command not recognized, trying XCUP\n");
+ (void) command("XCUP");
+ }
+}
+
+/* restart transfer at specific point */
+void
+restart(int argc, char *argv[])
+{
+ if (argc != 2)
+ printf("restart: offset not specified\n");
+ else {
+ restart_point = atol(argv[1]);
+ printf("restarting at %ld. %s\n", (long)restart_point,
+ "execute get, put or append to initiate transfer");
+ }
+}
+
+/* show remote system type */
+void
+syst(void)
+{
+ command("SYST");
+}
+
+void
+macdef(int argc, char *argv[])
+{
+ char *tmp;
+ int c;
+
+ if (macnum == 16) {
+ printf("Limit of 16 macros have already been defined\n");
+ code = -1;
+ return;
+ }
+ if (argc < 2 && !another(&argc, &argv, "macro name")) {
+ printf("Usage: %s macro_name\n",argv[0]);
+ code = -1;
+ return;
+ }
+ if (interactive) {
+ printf("Enter macro line by line, terminating it with a null line\n");
+ }
+ (void) strncpy(macros[macnum].mac_name, argv[1], 8);
+ macros[macnum].mac_name[8] = 0;
+ if (macnum == 0) {
+ macros[macnum].mac_start = macbuf;
+ }
+ else {
+ macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
+ }
+ tmp = macros[macnum].mac_start;
+ /* stepping over the end of the array, remember to take away 1! */
+ while (tmp != macbuf+MACBUF_SIZE) {
+ if ((c = getchar()) == EOF) {
+ printf("macdef:end of file encountered\n");
+ code = -1;
+ return;
+ }
+ if ((*tmp = c) == '\n') {
+ if (tmp == macros[macnum].mac_start) {
+ macros[macnum++].mac_end = tmp;
+ code = 0;
+ return;
+ }
+ if (*(tmp-1) == '\0') {
+ macros[macnum++].mac_end = tmp - 1;
+ code = 0;
+ return;
+ }
+ *tmp = '\0';
+ }
+ tmp++;
+ }
+ while (1) {
+ while ((c = getchar()) != '\n' && c != EOF)
+ /* LOOP */;
+ if (c == EOF || getchar() == '\n') {
+ printf("Macro not defined - 4k buffer exceeded\n");
+ code = -1;
+ return;
+ }
+ }
+}
+
+/*
+ * Start up passive mode interaction
+ */
+void
+setpassive(void)
+{
+ passivemode = !passivemode;
+ printf("Passive mode %s.\n", onoff(passivemode));
+ code = passivemode;
+}
+
+/*
+ * get size of file on remote machine
+ */
+void
+sizecmd(int argc, char *argv[])
+{
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ (void) command("SIZE %s", argv[1]);
+}
+
+/*
+ * get last modification time of file on remote machine
+ */
+void
+modtime(int argc, char *argv[])
+{
+ int overbose;
+
+ if (argc < 2 && !another(&argc, &argv, "filename")) {
+ printf("usage: %s filename\n", argv[0]);
+ code = -1;
+ return;
+ }
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ if (command("MDTM %s", argv[1]) == COMPLETE) {
+ int yy, mo, day, hour, min, sec;
+ sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
+ &day, &hour, &min, &sec);
+ /* might want to print this in local time */
+ printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1],
+ mo, day, yy, hour, min, sec);
+ } else
+ printf("%s\n", reply_string);
+ verbose = overbose;
+}
+
+/*
+ * show status on remote machine
+ */
+void
+rmtstatus(int argc, char *argv[])
+{
+ (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
+}
+
+/*
+ * get file if modtime is more recent than current file
+ */
+void
+newer(int argc, char *argv[])
+{
+ if (getit(argc, argv, -1, "w")) {
+ /* This should be controlled by some verbose flag */
+ printf("Local file \"%s\" is newer than remote file \"%s\"\n",
+ argv[2], argv[1]);
+ }
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/cmdtab.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/cmdtab.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/cmdtab.c (revision 5)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * from: @(#)cmdtab.c 5.10 (Berkeley) 6/1/90
+ */
+char cmdtab_rcsid[] =
+ "$Id: cmdtab.c,v 1.1.1.1 2000/11/03 19:18:15 mk Exp $";
+
+#include <string.h> /* for NULL */
+#include "ftp_var.h"
+#include "cmds.h"
+
+/*
+ * User FTP -- Command Tables.
+ */
+
+const char accounthelp[] = "send account command to remote server";
+const char appendhelp[] = "append to a file";
+const char asciihelp[] = "set ascii transfer type";
+const char beephelp[] = "beep when command completed";
+const char binaryhelp[] = "set binary transfer type";
+const char casehelp[] = "toggle mget upper/lower case id mapping";
+const char cdhelp[] = "change remote working directory";
+const char cduphelp[] = "change remote working directory to parent directory";
+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 deletehelp[] = "delete remote file";
+const char debughelp[] = "toggle/set debugging mode";
+const char dirhelp[] = "list contents of remote directory";
+const char disconhelp[] = "terminate ftp session";
+const char domachelp[] = "execute macro";
+const char formhelp[] = "set file transfer format";
+const char globhelp[] = "toggle metacharacter expansion of local file names";
+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 lcdhelp[] = "change local working directory";
+const char lshelp[] = "list contents of remote directory";
+const char macdefhelp[] = "define a macro";
+const char mdeletehelp[] = "delete multiple files";
+const char mdirhelp[] = "list contents of multiple remote directories";
+const char mgethelp[] = "get multiple files";
+const char mkdirhelp[] = "make directory on the remote machine";
+const char mlshelp[] = "list contents of multiple remote directories";
+const char modtimehelp[] = "show last modification time of remote file";
+const char modehelp[] = "set file transfer mode";
+const char mputhelp[] = "send multiple files";
+const char newerhelp[] = "get file if remote file is newer than local file ";
+const char nlisthelp[] = "nlist contents of remote directory";
+const char nmaphelp[] = "set templates for default file name mapping";
+const char ntranshelp[] ="set translation table for default file name mapping";
+const char passivehelp[] = "enter passive transfer mode";
+const char porthelp[] = "toggle use of PORT cmd for each data connection";
+const char prompthelp[] = "force interactive prompting on multiple commands";
+const char proxyhelp[] = "issue command on alternate connection";
+const char pwdhelp[] = "print working directory on remote machine";
+const char quithelp[] = "terminate ftp session and exit";
+const char quotehelp[] = "send arbitrary ftp command";
+const char receivehelp[] = "receive file";
+const char regethelp[] = "get file restarting at end of local file";
+const char remotehelp[] = "get help from remote server";
+const char renamehelp[] = "rename file";
+const char restarthelp[] = "restart file transfer at bytecount";
+const char rmdirhelp[] = "remove directory on the remote machine";
+const char rmtstatushelp[]="show status of remote machine";
+const char runiquehelp[] = "toggle store unique for local files";
+const char resethelp[] = "clear queued command replies";
+const char sendhelp[] = "send one file";
+const char sitehelp[] = "send site specific command to remote server\n"
+ "\t\tTry \"rhelp site\" or \"site help\" for more information";
+const char shellhelp[] = "escape to the shell";
+const char sizecmdhelp[] = "show size of remote file";
+const char statushelp[] = "show current status";
+const char structhelp[] = "set file transfer structure";
+const char suniquehelp[] = "toggle store unique on remote machine";
+const char systemhelp[] = "show remote system type";
+const char tenexhelp[] = "set tenex file transfer type";
+const char tickhelp[] = "toggle printing byte counter during transfers";
+const char tracehelp[] = "toggle packet tracing";
+const char typehelp[] = "set file transfer type";
+const char umaskhelp[] = "get (set) umask on remote side";
+const char userhelp[] = "send new user information";
+const char verbosehelp[] = "toggle verbose mode";
+
+struct cmd cmdtab[] = {
+ { "!", shellhelp, 0, 0, 0, NULL, NULL, shell },
+ { "$", domachelp, 1, 0, 0, domacro, NULL, NULL },
+ { "account", accounthelp, 0, 1, 1, account, NULL, NULL },
+ { "append", appendhelp, 1, 1, 1, put, NULL, NULL },
+ { "ascii", asciihelp, 0, 1, 1, NULL, setascii, NULL },
+ { "bell", beephelp, 0, 0, 0, NULL, setbell, NULL },
+ { "binary", binaryhelp, 0, 1, 1, NULL, setbinary, NULL },
+ { "bye", quithelp, 0, 0, 0, NULL, quit, NULL },
+ { "case", casehelp, 0, 0, 1, NULL, setcase, NULL },
+ { "cd", cdhelp, 0, 1, 1, cd, NULL, NULL },
+ { "cdup", cduphelp, 0, 1, 1, NULL, cdup, NULL },
+ { "chmod", chmodhelp, 0, 1, 1, do_chmod, NULL, NULL },
+ { "close", disconhelp, 0, 1, 1, NULL, disconnect, NULL },
+ { "cr", crhelp, 0, 0, 0, NULL, setcr, NULL },
+ { "delete", deletehelp, 0, 1, 1, delete_cmd, NULL, NULL },
+ { "debug", debughelp, 0, 0, 0, setdebug, NULL, NULL },
+ { "dir", dirhelp, 1, 1, 1, ls, NULL, NULL },
+ { "disconnect", disconhelp, 0, 1, 1, NULL, disconnect, NULL },
+ { "exit", quithelp, 0, 0, 0, NULL, quit, NULL },
+ { "form", formhelp, 0, 1, 1, NULL, setform, NULL },
+ { "get", receivehelp, 1, 1, 1, get, NULL, NULL },
+ { "glob", globhelp, 0, 0, 0, NULL, setglob, NULL },
+ { "hash", hashhelp, 0, 0, 0, NULL, sethash, NULL },
+ { "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 },
+ { "lcd", lcdhelp, 0, 0, 0, lcd, NULL, NULL },
+ { "ls", lshelp, 1, 1, 1, ls, NULL, NULL },
+ { "macdef", macdefhelp, 0, 0, 0, macdef, NULL, NULL },
+ { "mdelete", mdeletehelp, 1, 1, 1, mdelete, NULL, NULL },
+ { "mdir", mdirhelp, 1, 1, 1, mls, NULL, NULL },
+ { "mget", mgethelp, 1, 1, 1, mget, NULL, NULL },
+ { "mkdir", mkdirhelp, 0, 1, 1, makedir, NULL, NULL },
+ { "mls", mlshelp, 1, 1, 1, mls, NULL, NULL },
+ { "mode", modehelp, 0, 1, 1, NULL, setmode, NULL },
+ { "modtime", modtimehelp, 0, 1, 1, modtime, NULL, NULL },
+ { "mput", mputhelp, 1, 1, 1, mput, NULL, NULL },
+ { "newer", newerhelp, 1, 1, 1, newer, NULL, NULL },
+ { "nmap", nmaphelp, 0, 0, 1, setnmap, NULL, NULL },
+ { "nlist", nlisthelp, 1, 1, 1, ls, NULL, NULL },
+ { "ntrans", ntranshelp, 0, 0, 1, setntrans, NULL, NULL },
+ { "open", connecthelp, 0, 0, 1, setpeer, NULL, NULL },
+ { "prompt", prompthelp, 0, 0, 0, NULL, setprompt, NULL },
+ { "passive", passivehelp, 0, 0, 0, NULL, setpassive, NULL },
+ { "proxy", proxyhelp, 0, 0, 1, doproxy, NULL, 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 },
+ { "quit", quithelp, 0, 0, 0, NULL, quit, NULL },
+ { "quote", quotehelp, 1, 1, 1, quote, NULL, NULL },
+ { "recv", receivehelp, 1, 1, 1, get, NULL, NULL },
+ { "reget", regethelp, 1, 1, 1, reget, NULL, NULL },
+ { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus, NULL, NULL },
+ { "rhelp", remotehelp, 0, 1, 1, rmthelp, NULL, NULL },
+ { "rename", renamehelp, 0, 1, 1, renamefile, NULL, NULL },
+ { "reset", resethelp, 0, 1, 1, NULL, reset, NULL },
+ { "restart", restarthelp, 1, 1, 1, restart, NULL, NULL },
+ { "rmdir", rmdirhelp, 0, 1, 1, removedir, NULL, NULL },
+ { "runique", runiquehelp, 0, 0, 1, NULL, setrunique, NULL },
+ { "send", sendhelp, 1, 1, 1, put, NULL, NULL },
+ { "site", sitehelp, 0, 1, 1, site, NULL, NULL },
+ { "size", sizecmdhelp, 1, 1, 1, sizecmd, NULL, NULL },
+ { "status", statushelp, 0, 0, 1, NULL, status, NULL },
+ { "struct", structhelp, 0, 1, 1, NULL, setstruct, NULL },
+ { "system", systemhelp, 0, 1, 1, NULL, syst, NULL },
+ { "sunique", suniquehelp, 0, 0, 1, NULL, setsunique, NULL },
+ { "tenex", tenexhelp, 0, 1, 1, NULL, settenex, NULL },
+ { "tick", tickhelp, 0, 0, 0, NULL, settick, NULL },
+ { "trace", tracehelp, 0, 0, 0, NULL, settrace, NULL },
+ { "type", typehelp, 0, 1, 1, settype, NULL, NULL },
+ { "user", userhelp, 0, 1, 1, user, NULL, NULL },
+ { "umask", umaskhelp, 0, 1, 1, do_umask, NULL, NULL },
+ { "verbose", verbosehelp, 0, 0, 0, NULL, setverbose, NULL },
+ { "?", helphelp, 0, 0, 1, help, NULL, NULL },
+ { 0, 0, 0, 0, 0, 0, 0, 0 },
+};
+
+int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/domacro.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/domacro.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/domacro.c (revision 5)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * from: @(#)domacro.c 1.8 (Berkeley) 9/28/90
+ */
+char domacro_rcsid[] =
+ "$Id: domacro.c,v 1.1.1.1 2000/11/03 19:18:15 mk Exp $";
+
+#include <errno.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "ftp_var.h"
+
+void
+domacro(int argc, char *argv[])
+{
+ int margc;
+ char *marg;
+ char **margv;
+ register int i, j;
+ register char *cp1, *cp2;
+ int count = 2, loopflg = 0;
+ char line2[LINELEN];
+ struct cmd *c;
+
+ if (argc < 2 && !another(&argc, &argv, "macro name")) {
+ printf("Usage: %s macro_name.\n", argv[0]);
+ code = -1;
+ return;
+ }
+ for (i = 0; i < macnum; ++i) {
+ if (!strncmp(argv[1], macros[i].mac_name, 9)) {
+ break;
+ }
+ }
+ if (i == macnum) {
+ printf("'%s' macro not found.\n", argv[1]);
+ code = -1;
+ return;
+ }
+ (void) strcpy(line2, line);
+TOP:
+ cp1 = macros[i].mac_start;
+ while (cp1 != macros[i].mac_end) {
+ while (isspace(*cp1)) {
+ cp1++;
+ }
+ cp2 = line;
+ while (*cp1 != '\0') {
+ switch(*cp1) {
+ case '\\':
+ *cp2++ = *++cp1;
+ break;
+ case '$':
+ if (isdigit(*(cp1+1))) {
+ j = 0;
+ while (isdigit(*++cp1)) {
+ j = 10*j + *cp1 - '0';
+ }
+ cp1--;
+ if (argc - 2 >= j) {
+ (void) strcpy(cp2, argv[j+1]);
+ cp2 += strlen(argv[j+1]);
+ }
+ break;
+ }
+ if (*(cp1+1) == 'i') {
+ loopflg = 1;
+ cp1++;
+ if (count < argc) {
+ (void) strcpy(cp2, argv[count]);
+ cp2 += strlen(argv[count]);
+ }
+ break;
+ }
+ /* intentional drop through */
+ default:
+ *cp2++ = *cp1;
+ break;
+ }
+ if (*cp1 != '\0') {
+ cp1++;
+ }
+ }
+ *cp2 = '\0';
+ margv = makeargv(&margc, &marg);
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ code = -1;
+ }
+ else if (c == NULL) {
+ printf("?Invalid command\n");
+ code = -1;
+ }
+ else if (c->c_conn && !connected) {
+ printf("Not connected.\n");
+ code = -1;
+ }
+ else {
+ if (verbose) {
+ printf("%s\n",line);
+ }
+ if (c->c_handler_v) c->c_handler_v(margc, margv);
+ else if (c->c_handler_0) c->c_handler_0();
+ else c->c_handler_1(marg);
+
+ if (bell && c->c_bell) {
+ (void) putchar('\007');
+ }
+ (void) strcpy(line, line2);
+ margv = makeargv(&margc, &marg);
+ argc = margc;
+ argv = margv;
+ }
+ if (cp1 != macros[i].mac_end) {
+ cp1++;
+ }
+ }
+ if (loopflg && ++count < argc) {
+ goto TOP;
+ }
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.1
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.1 (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.1 (revision 5)
@@ -0,0 +1,1061 @@
+.\" Copyright (c) 1985, 1989, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. 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.
+.\"
+.\" from: @(#)ftp.1 6.18 (Berkeley) 7/30/91
+.\" $Id: ftp.1,v 1.1.1.1 2000/11/03 19:18:15 mk Exp $
+.\"
+.Dd August 15, 1999
+.Dt FTP 1
+.Os "Linux NetKit (0.17)"
+.Sh NAME
+.Nm ftp
+.Nd
+.Tn Internet
+file transfer program
+.Sh SYNOPSIS
+.Nm ftp
+.Op Fl pinegvd
+.Op Ar host
+.Nm pftp
+.Op Fl inegvd
+.Op Ar host
+.Sh DESCRIPTION
+.Nm Ftp
+is the user interface to the
+.Tn Internet
+standard File Transfer Protocol.
+The program allows a user to transfer files to and from a
+remote network site.
+.Pp
+Options may be specified at the command line, or to the
+command interpreter.
+.Bl -tag -width flag
+.It Fl A
+Use active mode for data transfers. This is useful for transmissions
+to servers which do not support passive connections (for whatever reason.)
+.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
+the client machine. Requires that the ftp server support the PASV
+command. This is the default now for
+.Nm all
+clients (ftp and pftp) due to security concerns using the PORT transfer mode.
+The flag is kept for compatibility only and has no effect anymore.
+.It Fl i
+Turns off interactive prompting during multiple file transfers.
+.It Fl n
+Restrains
+.Nm ftp
+from attempting \*(Lqauto-login\*(Rq upon initial connection.
+If auto-login is enabled,
+.Nm ftp
+will check the
+.Pa .netrc
+(see
+.Xr netrc 5)
+file in the user's home directory for an entry describing
+an account on the remote machine.
+If no entry exists,
+.Nm ftp
+will prompt for the remote machine login name (default is the user
+identity on the local machine), and, if necessary, prompt for a password
+and an account with which to login.
+.It Fl e
+Disables command editing and history support, if it was compiled into
+the
+.Nm ftp
+executable. Otherwise, does nothing.
+.It Fl g
+Disables file name globbing.
+.It Fl m
+The default requires that ftp explicitly binds to the same interface for the data
+channel as the control channel in passive mode. Useful on multi-homed
+clients. This option disables this behavior.
+.It Fl v
+Verbose option forces
+.Nm ftp
+to show all responses from the remote server, as well
+as report on data transfer statistics.
+.It Fl d
+Enables debugging.
+.El
+.Pp
+The client host with which
+.Nm ftp
+is to communicate may be specified on the command line.
+If this is done,
+.Nm ftp
+will immediately attempt to establish a connection to an
+.Tn FTP
+server on that host; otherwise,
+.Nm ftp
+will enter its command interpreter and await instructions
+from the user.
+When
+.Nm ftp
+is awaiting commands from the user the prompt
+.Ql ftp>
+is provided to the user.
+The following commands are recognized
+by
+.Nm ftp :
+.Bl -tag -width Fl
+.It Ic \&! Op Ar command Op Ar args
+Invoke an interactive shell on the local machine.
+If there are arguments, the first is taken to be a command to execute
+directly, with the rest of the arguments as its arguments.
+.It Ic \&$ Ar macro-name Op Ar args
+Execute the macro
+.Ar macro-name
+that was defined with the
+.Ic macdef
+command.
+Arguments are passed to the macro unglobbed.
+.It Ic account Op Ar passwd
+Supply a supplemental password required by a remote system for access
+to resources once a login has been successfully completed.
+If no argument is included, the user will be prompted for an account
+password in a non-echoing input mode.
+.It Ic append Ar local-file Op Ar remote-file
+Append a local file to a file on the remote machine.
+If
+.Ar remote-file
+is left unspecified, the local file name is used in naming the
+remote file after being altered by any
+.Ic ntrans
+or
+.Ic nmap
+setting.
+File transfer uses the current settings for
+.Ic type ,
+.Ic format ,
+.Ic mode ,
+and
+.Ic structure .
+.It Ic ascii
+Set the file transfer
+.Ic type
+to network
+.Tn ASCII .
+This is the default type.
+.It Ic bell
+Arrange that a bell be sounded after each file transfer
+command is completed.
+.It Ic binary
+Set the file transfer
+.Ic type
+to support binary image transfer.
+.It Ic bye
+Terminate the
+.Tn FTP
+session with the remote server
+and exit
+.Nm ftp .
+An end of file will also terminate the session and exit.
+.It Ic case
+Toggle remote computer file name case mapping during
+.Ic mget
+commands.
+When
+.Ic case
+is on (default is off), remote computer file names with all letters in
+upper case are written in the local directory with the letters mapped
+to lower case.
+.It Ic \&cd Ar remote-directory
+Change the working directory on the remote machine
+to
+.Ar remote-directory .
+.It Ic cdup
+Change the remote machine working directory to the parent of the
+current remote machine working directory.
+.It Ic chmod Ar mode file-name
+Change the permission modes of the file
+.Ar file-name
+on the remote
+system to
+.Ar mode .
+.It Ic close
+Terminate the
+.Tn FTP
+session with the remote server, and
+return to the command interpreter.
+Any defined macros are erased.
+.It Ic \&cr
+Toggle carriage return stripping during
+ascii type file retrieval.
+Records are denoted by a carriage return/linefeed sequence
+during ascii type file transfer.
+When
+.Ic \&cr
+is on (the default), carriage returns are stripped from this
+sequence to conform with the
+.Ux
+single linefeed record
+delimiter.
+Records on
+.Pf non\- Ns Ux
+remote systems may contain single linefeeds;
+when an ascii type transfer is made, these linefeeds may be
+distinguished from a record delimiter only when
+.Ic \&cr
+is off.
+.It Ic delete Ar remote-file
+Delete the file
+.Ar remote-file
+on the remote machine.
+.It Ic debug Op Ar debug-value
+Toggle debugging mode.
+If an optional
+.Ar debug-value
+is specified it is used to set the debugging level.
+When debugging is on,
+.Nm ftp
+prints each command sent to the remote machine, preceded
+by the string
+.Ql \-\->
+.It Xo
+.Ic dir
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a listing of the directory contents in the
+directory,
+.Ar remote-directory ,
+and, optionally, placing the output in
+.Ar local-file .
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic dir
+output.
+If no directory is specified, the current working
+directory on the remote machine is used.
+If no local
+file is specified, or
+.Ar local-file
+is
+.Fl ,
+output comes to the terminal.
+.It Ic disconnect
+A synonym for
+.Ar close .
+.It Ic form Ar format
+Set the file transfer
+.Ic form
+to
+.Ar format .
+The default format is \*(Lqfile\*(Rq.
+.It Ic get Ar remote-file Op Ar local-file
+Retrieve the
+.Ar remote-file
+and store it on the local machine.
+If the local
+file name is not specified, it is given the same
+name it has on the remote machine, subject to
+alteration by the current
+.Ic case ,
+.Ic ntrans ,
+and
+.Ic nmap
+settings.
+The current settings for
+.Ic type ,
+.Ic form ,
+.Ic mode ,
+and
+.Ic structure
+are used while transferring the file.
+.It Ic glob
+Toggle filename expansion for
+.Ic mdelete ,
+.Ic mget
+and
+.Ic mput .
+If globbing is turned off with
+.Ic glob ,
+the file name arguments
+are taken literally and not expanded.
+Globbing for
+.Ic mput
+is done as in
+.Xr csh 1 .
+For
+.Ic mdelete
+and
+.Ic mget ,
+each remote file name is expanded
+separately on the remote machine and the lists are not merged.
+Expansion of a directory name is likely to be
+different from expansion of the name of an ordinary file:
+the exact result depends on the foreign operating system and ftp server,
+and can be previewed by doing
+.Ql mls remote-files \-
+Note:
+.Ic mget
+and
+.Ic mput
+are not meant to transfer
+entire directory subtrees of files.
+That can be done by
+transferring a
+.Xr tar 1
+archive of the subtree (in binary mode).
+.It Ic hash
+Toggle hash-sign (``#'') printing for each data block
+transferred.
+The size of a data block is 1024 bytes.
+.It Ic help Op Ar command
+Print an informative message about the meaning of
+.Ar command .
+If no argument is given,
+.Nm ftp
+prints a list of the known commands.
+.It Ic idle Op Ar seconds
+Set the inactivity timer on the remote server to
+.Ar seconds
+seconds.
+If
+.Ar seconds
+is omitted, the current inactivity timer is printed.
+.It Ic lcd Op Ar directory
+Change the working directory on the local machine.
+If
+no
+.Ar directory
+is specified, the user's home directory is used.
+.It Xo
+.Ic \&ls
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a listing of the contents of a
+directory on the remote machine.
+The listing includes any system-dependent information that the server
+chooses to include; for example, most
+.Ux
+systems will produce
+output from the command
+.Ql ls \-l .
+(See also
+.Ic nlist . )
+If
+.Ar remote-directory
+is left unspecified, the current working directory is used.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic \&ls
+output.
+If no local file is specified, or if
+.Ar local-file
+is
+.Sq Fl ,
+the output is sent to the terminal.
+.It Ic macdef Ar macro-name
+Define a macro.
+Subsequent lines are stored as the macro
+.Ar macro-name ;
+a null line (consecutive newline characters
+in a file or
+carriage returns from the terminal) terminates macro input mode.
+There is a limit of 16 macros and 4096 total characters in all
+defined macros.
+Macros remain defined until a
+.Ic close
+command is executed.
+The macro processor interprets `$' and `\e' as special characters.
+A `$' followed by a number (or numbers) is replaced by the
+corresponding argument on the macro invocation command line.
+A `$' followed by an `i' signals that macro processor that the
+executing macro is to be looped.
+On the first pass `$i' is
+replaced by the first argument on the macro invocation command line,
+on the second pass it is replaced by the second argument, and so on.
+A `\e' followed by any character is replaced by that character.
+Use the `\e' to prevent special treatment of the `$'.
+.It Ic mdelete Op Ar remote-files
+Delete the
+.Ar remote-files
+on the remote machine.
+.It Ic mdir Ar remote-files local-file
+Like
+.Ic dir ,
+except multiple remote files may be specified.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic mdir
+output.
+.It Ic mget Ar remote-files
+Expand the
+.Ar remote-files
+on the remote machine
+and do a
+.Ic get
+for each file name thus produced.
+See
+.Ic glob
+for details on the filename expansion.
+Resulting file names will then be processed according to
+.Ic case ,
+.Ic ntrans ,
+and
+.Ic nmap
+settings.
+Files are transferred into the local working directory,
+which can be changed with
+.Ql lcd directory ;
+new local directories can be created with
+.Ql "\&! mkdir directory" .
+.It Ic mkdir Ar directory-name
+Make a directory on the remote machine.
+.It Ic mls Ar remote-files local-file
+Like
+.Ic nlist ,
+except multiple remote files may be specified,
+and the
+.Ar local-file
+must be specified.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic mls
+output.
+.It Ic mode Op Ar mode-name
+Set the file transfer
+.Ic mode
+to
+.Ar mode-name .
+The default mode is \*(Lqstream\*(Rq mode.
+.It Ic modtime Ar file-name
+Show the last modification time of the file on the remote machine.
+.It Ic mput Ar local-files
+Expand wild cards in the list of local files given as arguments
+and do a
+.Ic put
+for each file in the resulting list.
+See
+.Ic glob
+for details of filename expansion.
+Resulting file names will then be processed according to
+.Ic ntrans
+and
+.Ic nmap
+settings.
+.It Ic newer Ar file-name Op Ar local-file
+Get the file only if the modification time of the remote file is more
+recent that the file on the current system.
+If the file does not
+exist on the current system, the remote file is considered
+.Ic newer .
+Otherwise, this command is identical to
+.Ar get .
+.It Xo
+.Ic nlist
+.Op Ar remote-directory
+.Op Ar local-file
+.Xc
+Print a list of the files in a
+directory on the remote machine.
+If
+.Ar remote-directory
+is left unspecified, the current working directory is used.
+If interactive prompting is on,
+.Nm ftp
+will prompt the user to verify that the last argument is indeed the
+target local file for receiving
+.Ic nlist
+output.
+If no local file is specified, or if
+.Ar local-file
+is
+.Fl ,
+the output is sent to the terminal.
+.It Ic nmap Op Ar inpattern outpattern
+Set or unset the filename mapping mechanism.
+If no arguments are specified, the filename mapping mechanism is unset.
+If arguments are specified, remote filenames are mapped during
+.Ic mput
+commands and
+.Ic put
+commands issued without a specified remote target filename.
+If arguments are specified, local filenames are mapped during
+.Ic mget
+commands and
+.Ic get
+commands issued without a specified local target filename.
+This command is useful when connecting to a
+.No non\- Ns Ux
+remote computer
+with different file naming conventions or practices.
+The mapping follows the pattern set by
+.Ar inpattern
+and
+.Ar outpattern .
+.Op Ar Inpattern
+is a template for incoming filenames (which may have already been
+processed according to the
+.Ic ntrans
+and
+.Ic case
+settings).
+Variable templating is accomplished by including the
+sequences `$1', `$2', ..., `$9' in
+.Ar inpattern .
+Use `\\' to prevent this special treatment of the `$' character.
+All other characters are treated literally, and are used to determine the
+.Ic nmap
+.Op Ar inpattern
+variable values.
+For example, given
+.Ar inpattern
+$1.$2 and the remote file name "mydata.data", $1 would have the value
+"mydata", and $2 would have the value "data".
+The
+.Ar outpattern
+determines the resulting mapped filename.
+The sequences `$1', `$2', ...., `$9' are replaced by any value resulting
+from the
+.Ar inpattern
+template.
+The sequence `$0' is replace by the original filename.
+Additionally, the sequence
+.Ql Op Ar seq1 , Ar seq2
+is replaced by
+.Op Ar seq1
+if
+.Ar seq1
+is not a null string; otherwise it is replaced by
+.Ar seq2 .
+For example, the command
+.Pp
+.Bd -literal -offset indent -compact
+nmap $1.$2.$3 [$1,$2].[$2,file]
+.Ed
+.Pp
+would yield
+the output filename "myfile.data" for input filenames "myfile.data" and
+"myfile.data.old", "myfile.file" for the input filename "myfile", and
+"myfile.myfile" for the input filename ".myfile".
+Spaces may be included in
+.Ar outpattern ,
+as in the example: `nmap $1 sed "s/ *$//" > $1' .
+Use the `\e' character to prevent special treatment
+of the `$','[','[', and `,' characters.
+.It Ic ntrans Op Ar inchars Op Ar outchars
+Set or unset the filename character translation mechanism.
+If no arguments are specified, the filename character
+translation mechanism is unset.
+If arguments are specified, characters in
+remote filenames are translated during
+.Ic mput
+commands and
+.Ic put
+commands issued without a specified remote target filename.
+If arguments are specified, characters in
+local filenames are translated during
+.Ic mget
+commands and
+.Ic get
+commands issued without a specified local target filename.
+This command is useful when connecting to a
+.No non\- Ns Ux
+remote computer
+with different file naming conventions or practices.
+Characters in a filename matching a character in
+.Ar inchars
+are replaced with the corresponding character in
+.Ar outchars .
+If the character's position in
+.Ar inchars
+is longer than the length of
+.Ar outchars ,
+the character is deleted from the file name.
+.It Ic open Ar host Op Ar port
+Establish a connection to the specified
+.Ar host
+.Tn FTP
+server.
+An optional port number may be supplied,
+in which case,
+.Nm ftp
+will attempt to contact an
+.Tn FTP
+server at that port.
+If the
+.Ic auto-login
+option is on (default),
+.Nm ftp
+will also attempt to automatically log the user in to
+the
+.Tn FTP
+server (see below).
+.It Ic prompt
+Toggle interactive prompting.
+Interactive prompting
+occurs during multiple file transfers to allow the
+user to selectively retrieve or store files.
+If prompting is turned off (default is on), any
+.Ic mget
+or
+.Ic mput
+will transfer all files, and any
+.Ic mdelete
+will delete all files.
+.It Ic proxy Ar ftp-command
+Execute an ftp command on a secondary control connection.
+This command allows simultaneous connection to two remote ftp
+servers for transferring files between the two servers.
+The first
+.Ic proxy
+command should be an
+.Ic open ,
+to establish the secondary control connection.
+Enter the command "proxy ?" to see other ftp commands executable on the
+secondary connection.
+The following commands behave differently when prefaced by
+.Ic proxy :
+.Ic open
+will not define new macros during the auto-login process,
+.Ic close
+will not erase existing macro definitions,
+.Ic get
+and
+.Ic mget
+transfer files from the host on the primary control connection
+to the host on the secondary control connection, and
+.Ic put ,
+.Ic mput ,
+and
+.Ic append
+transfer files from the host on the secondary control connection
+to the host on the primary control connection.
+Third party file transfers depend upon support of the ftp protocol
+.Dv PASV
+command by the server on the secondary control connection.
+.It Ic put Ar local-file Op Ar remote-file
+Store a local file on the remote machine.
+If
+.Ar remote-file
+is left unspecified, the local file name is used
+after processing according to any
+.Ic ntrans
+or
+.Ic nmap
+settings
+in naming the remote file.
+File transfer uses the
+current settings for
+.Ic type ,
+.Ic format ,
+.Ic mode ,
+and
+.Ic structure .
+.It Ic pwd
+Print the name of the current working directory on the remote
+machine.
+.It Ic quit
+A synonym for
+.Ic bye .
+.It Ic quote Ar arg1 arg2 ...
+The arguments specified are sent, verbatim, to the remote
+.Tn FTP
+server.
+.It Ic recv Ar remote-file Op Ar local-file
+A synonym for get.
+.It Ic reget Ar remote-file Op Ar local-file
+Reget acts like get, except that if
+.Ar local-file
+exists and is
+smaller than
+.Ar remote-file ,
+.Ar local-file
+is presumed to be
+a partially transferred copy of
+.Ar remote-file
+and the transfer
+is continued from the apparent point of failure.
+This command
+is useful when transferring very large files over networks that
+are prone to dropping connections.
+.It Ic remotehelp Op Ar command-name
+Request help from the remote
+.Tn FTP
+server.
+If a
+.Ar command-name
+is specified it is supplied to the server as well.
+.It Ic remotestatus Op Ar file-name
+With no arguments, show status of remote machine.
+If
+.Ar file-name
+is specified, show status of
+.Ar file-name
+on remote machine.
+.It Xo
+.Ic rename
+.Op Ar from
+.Op Ar to
+.Xc
+Rename the file
+.Ar from
+on the remote machine, to the file
+.Ar to .
+.It Ic reset
+Clear reply queue.
+This command re-synchronizes command/reply sequencing with the remote
+ftp server.
+Resynchronization may be necessary following a violation of the ftp protocol
+by the remote server.
+.It Ic restart Ar marker
+Restart the immediately following
+.Ic get
+or
+.Ic put
+at the
+indicated
+.Ar marker .
+On
+.Ux
+systems, marker is usually a byte
+offset into the file.
+.It Ic rmdir Ar directory-name
+Delete a directory on the remote machine.
+.It Ic runique
+Toggle storing of files on the local system with unique filenames.
+If a file already exists with a name equal to the target
+local filename for a
+.Ic get
+or
+.Ic mget
+command, a ".1" is appended to the name.
+If the resulting name matches another existing file,
+a ".2" is appended to the original name.
+If this process continues up to ".99", an error
+message is printed, and the transfer does not take place.
+The generated unique filename will be reported.
+Note that
+.Ic runique
+will not affect local files generated from a shell command
+(see below).
+The default value is off.
+.It Ic send Ar local-file Op Ar remote-file
+A synonym for put.
+.It Ic sendport
+Toggle the use of
+.Dv PORT
+commands.
+By default,
+.Nm ftp
+will attempt to use a
+.Dv PORT
+command when establishing
+a connection for each data transfer.
+The use of
+.Dv PORT
+commands can prevent delays
+when performing multiple file transfers.
+If the
+.Dv PORT
+command fails,
+.Nm ftp
+will use the default data port.
+When the use of
+.Dv PORT
+commands is disabled, no attempt will be made to use
+.Dv PORT
+commands for each data transfer.
+This is useful
+for certain
+.Tn FTP
+implementations which do ignore
+.Dv PORT
+commands but, incorrectly, indicate they've been accepted.
+.It Ic site Ar arg1 arg2 ...
+The arguments specified are sent, verbatim, to the remote
+.Tn FTP
+server as a
+.Dv SITE
+command.
+.It Ic size Ar file-name
+Return size of
+.Ar file-name
+on remote machine.
+.It Ic status
+Show the current status of
+.Nm ftp .
+.It Ic struct Op Ar struct-name
+Set the file transfer
+.Ar structure
+to
+.Ar struct-name .
+By default \*(Lqstream\*(Rq structure is used.
+.It Ic sunique
+Toggle storing of files on remote machine under unique file names.
+Remote ftp server must support ftp protocol
+.Dv STOU
+command for
+successful completion.
+The remote server will report unique name.
+Default value is off.
+.It Ic system
+Show the type of operating system running on the remote machine.
+.It Ic tenex
+Set the file transfer type to that needed to
+talk to
+.Tn TENEX
+machines.
+.It Ic trace
+Toggle packet tracing.
+.It Ic type Op Ar type-name
+Set the file transfer
+.Ic type
+to
+.Ar type-name .
+If no type is specified, the current type
+is printed.
+The default type is network
+.Tn ASCII .
+.It Ic umask Op Ar newmask
+Set the default umask on the remote server to
+.Ar newmask .
+If
+.Ar newmask
+is omitted, the current umask is printed.
+.It Xo
+.Ic user Ar user-name
+.Op Ar password
+.Op Ar account
+.Xc
+Identify yourself to the remote
+.Tn FTP
+server.
+If the
+.Ar password
+is not specified and the server requires it,
+.Nm ftp
+will prompt the user for it (after disabling local echo).
+If an
+.Ar account
+field is not specified, and the
+.Tn FTP
+server
+requires it, the user will be prompted for it.
+If an
+.Ar account
+field is specified, an account command will
+be relayed to the remote server after the login sequence
+is completed if the remote server did not require it
+for logging in.
+Unless
+.Nm ftp
+is invoked with \*(Lqauto-login\*(Rq disabled, this
+process is done automatically on initial connection to
+the
+.Tn FTP
+server.
+.It Ic verbose
+Toggle verbose mode.
+In verbose mode, all responses from
+the
+.Tn FTP
+server are displayed to the user.
+In addition,
+if verbose is on, when a file transfer completes, statistics
+regarding the efficiency of the transfer are reported.
+By default,
+verbose is on.
+.It Ic ? Op Ar command
+A synonym for help.
+.El
+.Pp
+Command arguments which have embedded spaces may be quoted with
+quote `"' marks.
+.Sh ABORTING A FILE TRANSFER
+To abort a file transfer, use the terminal interrupt key
+(usually Ctrl-C).
+Sending transfers will be immediately halted.
+Receiving transfers will be halted by sending a ftp protocol
+.Dv ABOR
+command to the remote server, and discarding any further data received.
+The speed at which this is accomplished depends upon the remote
+server's support for
+.Dv ABOR
+processing.
+If the remote server does not support the
+.Dv ABOR
+command, an
+.Ql ftp>
+prompt will not appear until the remote server has completed
+sending the requested file.
+.Pp
+The terminal interrupt key sequence will be ignored when
+.Nm ftp
+has completed any local processing and is awaiting a reply
+from the remote server.
+A long delay in this mode may result from the ABOR processing described
+above, or from unexpected behavior by the remote server, including
+violations of the ftp protocol.
+If the delay results from unexpected remote server behavior, the local
+.Nm ftp
+program must be killed by hand.
+.Sh FILE NAMING CONVENTIONS
+Files specified as arguments to
+.Nm ftp
+commands are processed according to the following rules.
+.Bl -enum
+.It
+If the file name
+.Sq Fl
+is specified, the
+.Ar stdin
+(for reading) or
+.Ar stdout
+(for writing) is used.
+.It
+If the first character of the file name is
+.Sq \&| ,
+the
+remainder of the argument is interpreted as a shell command.
+.Nm Ftp
+then forks a shell, using
+.Xr popen 3
+with the argument supplied, and reads (writes) from the stdout
+(stdin).
+If the shell command includes spaces, the argument
+must be quoted; e.g.
+\*(Lq" ls -lt"\*(Rq.
+A particularly
+useful example of this mechanism is: \*(Lqdir more\*(Rq.
+.It
+Failing the above checks, if ``globbing'' is enabled,
+local file names are expanded
+according to the rules used in the
+.Xr csh 1 ;
+c.f. the
+.Ic glob
+command.
+If the
+.Nm ftp
+command expects a single local file (.e.g.
+.Ic put ) ,
+only the first filename generated by the "globbing" operation is used.
+.It
+For
+.Ic mget
+commands and
+.Ic get
+commands with unspecified local file names, the local filename is
+the remote filename, which may be altered by a
+.Ic case ,
+.Ic ntrans ,
+or
+.Ic nmap
+setting.
+The resulting filename may then be altered if
+.Ic runique
+is on.
+.It
+For
+.Ic mput
+commands and
+.Ic put
+commands with unspecified remote file names, the remote filename is
+the local filename, which may be altered by a
+.Ic ntrans
+or
+.Ic nmap
+setting.
+The resulting filename may then be altered by the remote server if
+.Ic sunique
+is on.
+.El
+.Sh FILE TRANSFER PARAMETERS
+The FTP specification specifies many parameters which may
+affect a file transfer.
+The
+.Ic type
+may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary),
+\*(Lqebcdic\*(Rq, and \*(Lqlocal byte size\*(Rq (for
+.Tn PDP Ns -10's
+and
+.Tn PDP Ns -20's
+mostly).
+.Nm Ftp
+supports the ascii and image types of file transfer,
+plus local byte size 8 for
+.Ic tenex
+mode transfers.
+.Pp
+.Nm Ftp
+supports only the default values for the remaining
+file transfer parameters:
+.Ic mode ,
+.Ic form ,
+and
+.Ic struct .
+.Sh ENVIRONMENT
+.Nm Ftp
+utilizes the following environment variables.
+.Bl -tag -width Fl
+.It Ev HOME
+For default location of a
+.Pa .netrc
+file, if one exists.
+.It Ev SHELL
+For default shell.
+.El
+.Sh SEE ALSO
+.Xr ftpd 8 ,
+RFC 959
+.Sh HISTORY
+The
+.Nm ftp
+command appeared in
+.Bx 4.2 .
+.Sh BUGS
+Correct execution of many commands depends upon proper behavior
+by the remote server.
+.Pp
+An error in the treatment of carriage returns
+in the
+.Bx 4.2
+ascii-mode transfer code
+has been corrected.
+This correction may result in incorrect transfers of binary files
+to and from
+.Bx 4.2
+servers using the ascii type.
+Avoid this problem by using the binary image type.
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp.c (revision 5)
@@ -0,0 +1,2001 @@
+/* $USAGI$ */
+
+/*
+ * Copyright (C) 1997 and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * From: @(#)ftp.c 5.38 (Berkeley) 4/22/91
+ */
+char ftp_rcsid[] =
+ "$Id: ftp.c,v 1.11 2001/02/11 12:26:59 yoshfuji Exp $";
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/poll.h>
+
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <arpa/ftp.h>
+#include <arpa/telnet.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+
+#include "ftp_var.h"
+#include "cmds.h"
+
+#ifdef _USAGI
+#include "version.h"
+#else
+#include "../version.h"
+#endif
+
+union sockunion {
+ struct sockinet {
+ u_short si_family;
+ u_short si_port;
+ } su_si;
+ struct sockaddr su_sa;
+ struct sockaddr_in su_sin;
+#ifdef INET6
+ struct sockaddr_in6 su_sin6;
+#endif
+};
+#define su_family su_sa.sa_family
+#define su_port su_si.si_port
+
+#ifdef INET6
+#define ex_af2prot(a) (a == AF_INET ? 1 : (a == AF_INET6 ? 2 : 0))
+#else
+#define ex_af2prot(a) (a == AF_INET ? 1 : 0)
+#endif
+
+int data = -1;
+off_t restart_point = 0;
+
+static union sockunion hisctladdr;
+static union sockunion data_addr;
+static union sockunion 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;
+struct sockaddr_storage source;
+
+void lostpeer(int);
+extern int connected;
+
+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 long bytes,
+ const struct timeval *t0,
+ const struct timeval *t1);
+static void tvsub(struct timeval *tdiff,
+ const struct timeval *t1,
+ const struct timeval *t0);
+static void abort_remote(FILE *din);
+
+FILE *cin, *cout;
+static FILE *dataconn(const char *);
+
+char *
+hookup(const char *host, const char *port)
+{
+ int s, tos, error;
+ socklen_t len, alen;
+ static char hostnamebuf[256];
+ struct addrinfo hints, *res, *res0;
+ char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV];
+ char *cause = "ftp: unknown";
+
+ if (port) {
+ strncpy(pbuf, port, sizeof(pbuf) - 1);
+ pbuf[sizeof(pbuf) - 1] = '\0';
+ } else {
+ sprintf(pbuf, "%d", ntohs(ftp_port));
+ }
+ memset(&hisctladdr, 0, sizeof(hisctladdr));
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(host, pbuf, &hints, &res0);
+ if (error) {
+ if (port) {
+ strcpy(hbuf, " ");
+ } else {
+ hbuf[0] = '\0';
+ pbuf[0] = '\0';
+ }
+ fprintf(stderr, "ftp: %s%s%s: %s\n", host, hbuf, pbuf,
+ gai_strerror(error));
+ code = -1;
+ return (0);
+ }
+
+ if (res0->ai_canonname) {
+ struct addrinfo h, *a;
+ memset(&h, 0, sizeof(h));
+ h.ai_family = PF_UNSPEC;
+ h.ai_socktype = SOCK_STREAM;
+ h.ai_flags = AI_NUMERICHOST;
+ if (!getaddrinfo(res0->ai_canonname, NULL, &h, &a)) {
+ strncpy(hostnamebuf, res0->ai_canonname, sizeof(hostnamebuf));
+ freeaddrinfo(a);
+ } else
+ strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+ }
+ else
+ strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+ hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
+ hostname = hostnamebuf;
+
+ s = -1;
+ for (res = res0; res; res = res->ai_next) {
+ if (!ex_af2prot(res->ai_family)) {
+ cause = "ftp: mismatch address family";
+ errno = EPROTONOSUPPORT;
+ continue;
+ }
+ if ((size_t)res->ai_addrlen > sizeof(hisctladdr)) {
+ cause = "ftp: mismatch struct sockaddr size";
+ errno = EPROTO;
+ continue;
+ }
+ if (getnameinfo(res->ai_addr, res->ai_addrlen,
+ hbuf, sizeof(hbuf), NULL, 0,
+ NI_NUMERICHOST))
+ strcpy(hbuf, "???");
+ if (res0->ai_next) /* if we have multiple possibilities */
+ fprintf(stdout, "Trying %s...\n", hbuf);
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (s < 0) {
+ cause = "ftp: socket";
+ continue;
+ }
+ while ((error = connect(s, res->ai_addr, res->ai_addrlen)) < 0
+ && errno == EINTR) {
+ ;
+ }
+ if (error) {
+ /* this "if" clause is to prevent print warning twice */
+ if (res->ai_next) {
+ fprintf(stderr,
+ "ftp: connect to address %s", hbuf);
+ perror("");
+ }
+ cause = "ftp: connect";
+ close(s);
+ s = -1;
+ continue;
+ }
+ /* finally we got one */
+ break;
+ }
+ if (s < 0) {
+ perror(cause);
+ code = -1;
+ freeaddrinfo(res0);
+ return NULL;
+ }
+ len = res->ai_addrlen;
+ memcpy(&hisctladdr, res->ai_addr, len);
+ freeaddrinfo(res0);
+ if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
+ perror("ftp: getsockname");
+ code = -1;
+ goto bad;
+ }
+#ifdef IP_TOS
+ if (hisctladdr.su_family == AF_INET)
+ {
+ tos = IPTOS_LOWDELAY;
+ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+ perror("ftp: setsockopt TOS (ignored)");
+ }
+#endif
+ cin = fdopen(s, "r");
+ cout = fdopen(s, "w");
+ if (cin == NULL || cout == NULL) {
+ fprintf(stderr, "ftp: fdopen failed.\n");
+ if (cin)
+ (void) fclose(cin);
+ if (cout)
+ (void) fclose(cout);
+ code = -1;
+ goto bad;
+ }
+ if (verbose)
+ printf("Connected to %s (%s).\n", hostname, hbuf);
+ alen = sizeof(source);
+ getsockname(s,(struct sockaddr*)&source, &alen);
+ switch (source.ss_family) {
+ /* We just want the addr, not the port */
+ case AF_INET:
+ ((struct sockaddr_in *) &source)->sin_port = 0;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *) &source)->sin6_port = 0;
+ break;
+ }
+
+ if (getreply(0) > 2) { /* read startup message from server */
+ if (cin)
+ (void) fclose(cin);
+ if (cout)
+ (void) fclose(cout);
+ code = -1;
+ goto bad;
+ }
+#ifdef SO_OOBINLINE
+ {
+ int on = 1;
+
+ if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
+ < 0 && debug) {
+ perror("ftp: setsockopt");
+ }
+ }
+#endif /* SO_OOBINLINE */
+
+ return (hostname);
+bad:
+ (void) close(s);
+ return ((char *)0);
+}
+
+int
+dologin(const char *host)
+{
+ char tmp[80];
+ char *luser, *pass, *zacct;
+ int n, aflag = 0;
+
+ luser = pass = zacct = 0;
+ if (xruserpass(host, &luser, &pass, &zacct) < 0) {
+ code = -1;
+ return(0);
+ }
+ while (luser == NULL) {
+ char *myname = NULL;
+
+ struct passwd *pp = getpwuid(getuid());
+
+ if (pp != NULL)
+ myname = pp->pw_name;
+ if (myname)
+ printf("Name (%s:%s): ", host, myname);
+ else
+ printf("Name (%s): ", host);
+ if (fgets(tmp, sizeof(tmp) - 1, stdin)==NULL) {
+ fprintf(stderr, "\nLogin failed.\n");
+ return 0;
+ }
+ tmp[strlen(tmp) - 1] = '\0';
+ if (*tmp == '\0')
+ luser = myname;
+ else
+ luser = tmp;
+ }
+ n = command("USER %s", luser);
+ if (n == CONTINUE) {
+ if (pass == NULL) {
+ /* fflush(stdout); */
+ pass = getpass("Password:");
+ }
+ n = command("PASS %s", pass);
+ }
+ if (n == CONTINUE) {
+ aflag++;
+ /* fflush(stdout); */
+ if(zacct==NULL)
+ zacct = getpass("Account:");
+ n = command("ACCT %s", zacct);
+ }
+ if (n != COMPLETE) {
+ fprintf(stderr, "Login failed.\n");
+ return (0);
+ }
+ if (!aflag && zacct != NULL)
+ (void) command("ACCT %s", zacct);
+ if (proxy)
+ return(1);
+ for (n = 0; n < macnum; ++n) {
+ if (!strcmp("init", macros[n].mac_name)) {
+ int margc;
+ char **margv;
+ strcpy(line, "$init");
+ margv = makeargv(&margc, NULL);
+ domacro(margc, margv);
+ 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);
+ va_end(ap);
+ printf("\n");
+ (void) fflush(stdout);
+ }
+ if (cout == NULL) {
+ perror ("No control connection for command");
+ code = -1;
+ return (0);
+ }
+ oldintr = signal(SIGINT, cmdabort);
+ va_start(ap, fmt);
+ vfprintf(cout, fmt, ap);
+ va_end(ap);
+ fprintf(cout, "\r\n");
+ (void) fflush(cout);
+ cpend = 1;
+ r = getreply(!strcmp(fmt, "QUIT"));
+ if (abrtflag && oldintr != SIG_IGN)
+ (*oldintr)(SIGINT);
+ (void) signal(SIGINT, oldintr);
+ return(r);
+}
+
+char reply_string[BUFSIZ]; /* last line of previous reply */
+
+#include <ctype.h>
+
+int
+getreply(int expecteof)
+{
+ register int c, n;
+ 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);
+ for (;;) {
+ dig = n = code = 0;
+ cp = reply_string;
+ while ((c = getc(cin)) != '\n') {
+ if (c == IAC) { /* handle telnet commands */
+ switch (c = getc(cin)) {
+ case WILL:
+ case WONT:
+ c = getc(cin);
+ fprintf(cout, "%c%c%c", IAC, DONT, c);
+ (void) fflush(cout);
+ break;
+ case DO:
+ case DONT:
+ c = getc(cin);
+ fprintf(cout, "%c%c%c", IAC, WONT, c);
+ (void) fflush(cout);
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ dig++;
+ if (c == EOF) {
+ if (expecteof) {
+ (void) signal(SIGINT,oldintr);
+ code = 221;
+ return (0);
+ }
+ lostpeer(0);
+ if (cout) {
+ fclose(cout);
+ cout = NULL;
+ }
+ if (verbose) {
+ printf("421 Service not available, remote server has closed connection\n");
+ (void) fflush(stdout);
+ }
+ code = 421;
+ return(4);
+ }
+ if (c != '\r' && (verbose > 0 ||
+ (verbose > -1 && n == '5' && dig > 4))) {
+ if (proxflag &&
+ (dig == 1 || (dig == 5 && verbose == 0)))
+ printf("%s:",hostname);
+ (void) putchar(c);
+ }
+ if (dig < 4 && isdigit(c))
+ code = code * 10 + (c - '0');
+ if (!pflag && (code == 227 || code == 228))
+ pflag = 1;
+ else if (!pflag && code == 229)
+ pflag = 100;
+ if (dig > 4 && pflag == 1 && isdigit(c))
+ pflag = 2;
+ if (pflag == 2) {
+ if (c != '\r' && c != ')') {
+ if (px < psize-1) pasv[px++] = c;
+ }
+ else {
+ pasv[px] = '\0';
+ pflag = 3;
+ }
+ }
+ if (pflag == 100 && c == '(')
+ pflag = 2;
+ if (dig == 4 && c == '-') {
+ if (continuation)
+ code = 0;
+ continuation++;
+ }
+ if (n == 0)
+ n = c;
+ if (cp < &reply_string[sizeof(reply_string) - 1])
+ *cp++ = c;
+ }
+ if (verbose > 0 || (verbose > -1 && n == '5')) {
+ (void) putchar(c);
+ (void) fflush (stdout);
+ }
+ if (continuation && code != originalcode) {
+ if (originalcode == 0)
+ originalcode = code;
+ continue;
+ }
+ *cp = '\0';
+ if (n != '1')
+ cpend = 0;
+ (void) signal(SIGINT,oldintr);
+ if (code == 421 || originalcode == 421)
+ {
+ lostpeer(0);
+ if(cout)
+ {
+ fclose(cout);
+ cout = NULL;
+ }
+ }
+ if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
+ (*oldintr)(SIGINT);
+ return (n - '0');
+ }
+}
+
+static int
+empty(fd_set *mask, int hifd, int sec)
+{
+ struct timeval t;
+
+ t.tv_sec = (long) sec;
+ t.tv_usec = 0;
+ return(select(hifd+1, mask, (fd_set *) 0, (fd_set *) 0, &t));
+}
+
+static void
+abortsend(int ignore)
+{
+ (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
+
+void
+sendrequest(const char *cmd, char *local, char *remote, int printnames)
+{
+ struct stat st;
+ struct timeval start, stop;
+ register int c, d;
+ FILE *volatile fin, *volatile dout = 0;
+ int (*volatile closefunc)(FILE *);
+ void (*volatile oldintr)(int);
+ void (*volatile oldintp)(int);
+ volatile long long bytes = 0, hashbytes = HASHBYTES;
+ char buf[BUFSIZ], *bufp;
+ const char *volatile lmode;
+ int old_code_l;
+
+ if (verbose && printnames) {
+ if (local && *local != '-')
+ printf("local: %s ", local);
+ if (remote)
+ printf("remote: %s\n", remote);
+ }
+ if (proxy) {
+ proxtrans(cmd, local, remote);
+ return;
+ }
+ if (curtype != type)
+ changetype(type, 0);
+ closefunc = NULL;
+ oldintr = NULL;
+ oldintp = NULL;
+ lmode = "w";
+ if (sigsetjmp(sendabort, 1)) {
+ while (cpend) {
+ (void) getreply(0);
+ }
+ if (data >= 0) {
+ (void) close(data);
+ data = -1;
+ }
+ if (oldintr)
+ (void) signal(SIGINT,oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE,oldintp);
+ code = -1;
+ return;
+ }
+ oldintr = signal(SIGINT, abortsend);
+ if (strcmp(local, "-") == 0)
+ fin = stdin;
+ else if (*local == '|') {
+ oldintp = signal(SIGPIPE,SIG_IGN);
+ fin = popen(local + 1, "r");
+ if (fin == NULL) {
+ perror(local + 1);
+ (void) signal(SIGINT, oldintr);
+ (void) signal(SIGPIPE, oldintp);
+ code = -1;
+ return;
+ }
+ closefunc = pclose;
+ } else {
+ fin = fopen(local, "r");
+ if (fin == NULL) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ (void) signal(SIGINT, oldintr);
+ 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);
+ fclose(fin);
+ code = -1;
+ return;
+ }
+ }
+ if (initconn()) {
+ (void) signal(SIGINT, oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ code = -1;
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ if (sigsetjmp(sendabort, 1))
+ goto abort;
+
+ if (restart_point &&
+ (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
+ if (fseek(fin, (long) restart_point, 0) < 0) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ restart_point = 0;
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ if (command("REST %ld", (long) restart_point)
+ != CONTINUE) {
+ restart_point = 0;
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ restart_point = 0;
+ lmode = "r+w";
+ }
+ if (remote) {
+ if (command("%s %s", cmd, remote) != PRELIM) {
+ (void) signal(SIGINT, oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ } else
+ if (command("%s", cmd) != PRELIM) {
+ (void) signal(SIGINT, oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ dout = dataconn(lmode);
+ if (dout == NULL)
+ goto abort;
+ (void) gettimeofday(&start, (struct timezone *)0);
+ oldintp = signal(SIGPIPE, SIG_IGN);
+ switch (curtype) {
+
+ case TYPE_I:
+ case TYPE_L:
+ errno = d = 0;
+ 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)
+ break;
+ if (hash) {
+ while (bytes >= hashbytes) { /* <-- 'long long' signed overflow is */
+ (void) putchar('#'); /* possible. In this case, we can */
+ hashbytes += HASHBYTES; /* 'cycle' there for very long time. */
+ } /* Search 'hasbytes' in file down, */
+ (void) fflush(stdout); /* there are similar parts. */
+ } /* <praszyk@redhat.com> */
+ if (tick && (bytes >= hashbytes)) {
+ printf("\rBytes transferred: %lld", bytes);
+ (void) fflush(stdout);
+ while (bytes >= hashbytes)
+ hashbytes += TICKBYTES;
+ }
+ }
+ if (hash && (bytes > 0)) {
+ if (bytes < HASHBYTES)
+ (void) putchar('#');
+ (void) putchar('\n');
+ (void) fflush(stdout);
+ }
+ if (tick) {
+ (void) printf("\rBytes transferred: %lld\n", bytes);
+ (void) fflush(stdout);
+ }
+ if (c < 0)
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (d < 0) {
+ if (errno != EPIPE)
+ perror("netout");
+ bytes = -1;
+ }
+ break;
+
+ case TYPE_A:
+ while ((c = getc(fin)) != EOF) {
+ if (c == '\n') {
+ while (hash && (bytes >= hashbytes)) {
+ (void) putchar('#');
+ (void) fflush(stdout);
+ hashbytes += HASHBYTES;
+ }
+ if (tick && (bytes >= hashbytes)) {
+ (void) printf("\rBytes transferred: %lld",
+ bytes);
+ (void) fflush(stdout);
+ while (bytes >= hashbytes)
+ hashbytes += TICKBYTES;
+ }
+ if (ferror(dout))
+ break;
+ (void) putc('\r', dout);
+ bytes++;
+ }
+ (void) putc(c, dout);
+ bytes++;
+ /* if (c == '\r') { */
+ /* (void) putc('\0', dout); (* this violates rfc */
+ /* bytes++; */
+ /* } */
+ }
+ if (hash) {
+ if (bytes < hashbytes)
+ (void) putchar('#');
+ (void) putchar('\n');
+ (void) fflush(stdout);
+ }
+ if (tick) {
+ (void) printf("\rBytes transferred: %lld\n", bytes);
+ (void) fflush(stdout);
+ }
+ if (ferror(fin))
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (ferror(dout)) {
+ if (errno != EPIPE)
+ perror("netout");
+ bytes = -1;
+ }
+ break;
+ }
+ (void) gettimeofday(&stop, (struct timezone *)0);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ (void) fclose(dout);
+ /* closes data as well, so discard it */
+ data = -1;
+ old_code_l = code;
+ (void) getreply(0);
+
+ /* Following "if" will avoid a bug #165083 in ftp-server */
+ /* It can be later removed. */
+ if (old_code_l == 150 && code == 150 && cpend == 1
+ && sunique == 1 && cin != NULL && fileno (cin) >= 0 ) {
+ struct pollfd fds_events_l [2] ;
+ int rc;
+
+ fds_events_l [0] .fd = fileno (cin);
+ fds_events_l [0] .events = POLLIN | POLLERR | POLLHUP;
+
+ rc = poll (fds_events_l, 1, 5000);
+ switch (rc) {
+ case 1:
+ (void) getreply (0);
+ break;
+ case 0:
+ fprintf (stderr, "ftp: no answer from ftp-server "
+ "(more than 5 sec).\n");
+ break;
+ case -1:
+ perror("ftp: poll");
+ break;
+ }
+ }
+
+ (void) signal(SIGINT, oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ 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;
+ return;
+ }
+ if (dout) {
+ (void) fclose(dout);
+ }
+ if (data >= 0) {
+ /* if it just got closed with dout, again won't hurt */
+ (void) close(data);
+ data = -1;
+ }
+ (void) getreply(0);
+ code = -1;
+ if (closefunc != NULL && fin != NULL)
+ (*closefunc)(fin);
+ if (bytes > 0)
+ ptransfer("sent", bytes, &start, &stop);
+}
+
+static void
+abortrecv(int ignore)
+{
+ (void)ignore;
+
+ mflag = 0;
+ abrtflag = 0;
+ printf("\nreceive aborted\nwaiting for remote to finish abort\n");
+ (void) fflush(stdout);
+ siglongjmp(recvabort, 1);
+}
+
+void
+recvrequest(const char *cmd,
+ char *volatile local, char *remote,
+ const char *lmode, int printnames)
+{
+ FILE *volatile fout, *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=0;
+ static char *buf;
+ volatile long long bytes = 0, hashbytes = HASHBYTES;
+ register int c, d;
+ struct timeval start, stop;
+ struct stat st;
+
+ is_retr = strcmp(cmd, "RETR") == 0;
+ if (is_retr && verbose && printnames) {
+ if (local && *local != '-')
+ printf("local: %s ", local);
+ if (remote)
+ printf("remote: %s\n", remote);
+ }
+ if (proxy && is_retr) {
+ proxtrans(cmd, local, remote);
+ return;
+ }
+ closefunc = NULL;
+ oldintr = NULL;
+ oldintp = NULL;
+ tcrflag = !crflag && is_retr;
+ if (sigsetjmp(recvabort, 1)) {
+ while (cpend) {
+ (void) getreply(0);
+ }
+ if (data >= 0) {
+ (void) close(data);
+ data = -1;
+ }
+ if (oldintr)
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ oldintr = signal(SIGINT, abortrecv);
+ if (strcmp(local, "-") && *local != '|') {
+ if (access(local, W_OK) < 0) {
+ char *dir = rindex(local, '/');
+
+ if (errno != ENOENT && errno != EACCES) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (dir != NULL)
+ *dir = 0;
+ d = access(dir ? local : ".", W_OK);
+ if (dir != NULL)
+ *dir = '/';
+ if (d < 0) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (!runique && errno == EACCES &&
+ 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);*/
+ code = -1;
+ return;
+ }
+ if (runique && errno == EACCES &&
+ (local = gunique(local)) == NULL) {
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ }
+ else if (runique && (strcmp(cmd, "NLST") != 0) &&
+ (local = gunique(local)) == NULL)
+ {
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ }
+ if (!is_retr) {
+ if (curtype != TYPE_A)
+ changetype(TYPE_A, 0);
+ }
+ else if (curtype != type) {
+ changetype(type, 0);
+ }
+ if (initconn()) {
+ (void) signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (sigsetjmp(recvabort, 1))
+ goto abort;
+ if (is_retr && restart_point &&
+ command("REST %ld", (long) restart_point) != CONTINUE)
+ return;
+ if (remote) {
+ if (command("%s %s", cmd, remote) != PRELIM) {
+ (void) signal(SIGINT, oldintr);
+ return;
+ }
+ }
+ else {
+ if (command("%s", cmd) != PRELIM) {
+ (void) signal(SIGINT, oldintr);
+ return;
+ }
+ }
+ din = dataconn("r");
+ if (din == NULL)
+ goto abort;
+ if (strcmp(local, "-") == 0)
+ fout = stdout;
+ else if (*local == '|') {
+ oldintp = signal(SIGPIPE, SIG_IGN);
+ fout = popen(local + 1, "w");
+ if (fout == NULL) {
+ perror(local+1);
+ goto abort;
+ }
+ closefunc = pclose;
+ }
+ else {
+ fout = fopen(local, lmode);
+ 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 ((unsigned)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 = st.st_blksize;
+ }
+ (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) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (closefunc != NULL)
+ (*closefunc)(fout);
+ return;
+ }
+ errno = d = 0;
+ while ((c = read(fileno(din), buf, bufsize)) > 0) {
+ if ((d = write(fileno(fout), buf, c)) != c)
+ break;
+ bytes += c;
+ if (hash && is_retr) {
+ while (bytes >= hashbytes) {
+ (void) putchar('#');
+ hashbytes += HASHBYTES;
+ }
+ (void) fflush(stdout);
+ }
+ if (tick && (bytes >= hashbytes) && is_retr) {
+ (void) printf("\rBytes transferred: %lld",
+ bytes);
+ (void) fflush(stdout);
+ while (bytes >= hashbytes)
+ hashbytes += TICKBYTES;
+ }
+ }
+ if (hash && bytes > 0) {
+ if (bytes < HASHBYTES)
+ (void) putchar('#');
+ (void) putchar('\n');
+ (void) fflush(stdout);
+ }
+ if (tick && is_retr) {
+ (void) printf("\rBytes transferred: %lld\n", bytes);
+ (void) fflush(stdout);
+ }
+ if (c < 0) {
+ if (errno != EPIPE)
+ perror("netin");
+ bytes = -1;
+ }
+ if (d < c) {
+ if (d < 0)
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ else
+ fprintf(stderr, "%s: short write\n", local);
+ }
+ break;
+
+ case TYPE_A:
+ if (restart_point) {
+ register int i, n, ch;
+
+ if (fseek(fout, 0L, L_SET) < 0)
+ goto done;
+ n = restart_point;
+ for (i = 0; i++ < n;) {
+ if ((ch = getc(fout)) == EOF)
+ goto done;
+ if (ch == '\n')
+ i++;
+ }
+ if (fseek(fout, 0L, L_INCR) < 0) {
+done:
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (closefunc != NULL)
+ (*closefunc)(fout);
+ return;
+ }
+ }
+ while ((c = getc(din)) != EOF) {
+ if (c == '\n')
+ bare_lfs++;
+ while (c == '\r') {
+ while (hash && (bytes >= hashbytes)
+ && is_retr) {
+ (void) putchar('#');
+ (void) fflush(stdout);
+ hashbytes += HASHBYTES;
+ }
+ if (tick && (bytes >= hashbytes) && is_retr) {
+ printf("\rBytes transferred: %lld",
+ bytes);
+ fflush(stdout);
+ while (bytes >= hashbytes)
+ hashbytes += TICKBYTES;
+ }
+ bytes++;
+ if ((c = getc(din)) != '\n' || tcrflag) {
+ if (ferror(fout))
+ goto break2;
+ (void) putc('\r', fout);
+ if (c == '\0') {
+ bytes++;
+ goto contin2;
+ }
+ if (c == EOF)
+ goto contin2;
+ }
+ }
+ (void) putc(c, fout);
+ bytes++;
+ contin2: ;
+ }
+break2:
+ if (hash && is_retr) {
+ if (bytes < hashbytes)
+ (void) putchar('#');
+ (void) putchar('\n');
+ (void) fflush(stdout);
+ }
+ if (tick && is_retr) {
+ (void) printf("\rBytes transferred: %lld\n", bytes);
+ (void) fflush(stdout);
+ }
+ 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");
+ bytes = -1;
+ }
+ if (ferror(fout))
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ break;
+ }
+ if (closefunc != NULL)
+ (*closefunc)(fout);
+ (void) signal(SIGINT, oldintr);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ (void) gettimeofday(&stop, (struct timezone *)0);
+ (void) fclose(din);
+ /* closes data as well, so discard it */
+ data = -1;
+ (void) getreply(0);
+ if (bytes > 0 && is_retr)
+ ptransfer("received", bytes, &start, &stop);
+ return;
+abort:
+
+/* abort using RFC959 recommended IP,SYNC sequence */
+
+ (void) gettimeofday(&stop, (struct timezone *)0);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ (void) signal(SIGINT, SIG_IGN);
+ if (!cpend) {
+ code = -1;
+ (void) signal(SIGINT, oldintr);
+ return;
+ }
+
+ abort_remote(din);
+ code = -1;
+ if (closefunc != NULL && fout != NULL)
+ (*closefunc)(fout);
+ if (din) {
+ (void) fclose(din);
+ }
+ 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);
+}
+
+/*
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
+ */
+static int
+initconn(void)
+{
+ int rc;
+ u_char *p, *a;
+ int result, tmpno = 0;
+ socklen_t len;
+ int on = 1;
+ int tos, error = 0;
+ u_int ad[16], po[2], af, alen, plen;
+ char *pasvcmd = NULL;
+ char hbuf[MAXHOSTNAMELEN], pbuf[NI_MAXSERV];
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+#ifdef INET6
+ if (myctladdr.su_family == AF_INET6
+ && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
+ || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
+ fprintf(stderr, "use of scoped address can be troublesome\n");
+ }
+#endif
+ if (passivemode) {
+ if (data >= 0){
+ rc = close (data);
+ data = -1;
+ if (rc == -1){
+ perror ("ftp: close");
+ }
+ }
+ data_addr = hisctladdr;
+ data = socket(data_addr.su_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ perror("ftp: socket");
+ return(1);
+ }
+ if((multihome) &&
+ bind(data, (struct sockaddr *)&source, sizeof(source)) == -1) {
+ close(data);
+ data = -1;
+ perror("ftp multihome bind");
+ return(1);
+ }
+ if (options & SO_DEBUG &&
+ setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
+ sizeof (on)) < 0)
+ perror("ftp: setsockopt (ignored)");
+ switch (data_addr.su_family) {
+ case AF_INET:
+#if 0
+/*@*/ if (try_epsv) {
+/*@*/ result = command(pasvcmd = "EPSV 1");
+/*@*/ if (code / 10 == 22 && code != 229) {
+/*@*/ fprintf(stderr,
+/*@*/ "wrong server: return code must be 229\n");
+/*@*/ result = COMPLETE + 1;
+/*@*/ }
+/*@*/ } else {
+#endif
+ result = COMPLETE + 1;
+
+ if (result != COMPLETE) {
+ try_epsv = 0;
+ result = command(pasvcmd = "PASV");
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (try_epsv) {
+ result = command(pasvcmd = "EPSV 2");
+ if (code / 10 == 22 && code != 229) {
+ fprintf(stderr,
+ "wrong server: return code must be 229\n");
+ result = COMPLETE + 1;
+ }
+ } else {
+ result = COMPLETE + 1;
+ }
+ if (result != COMPLETE) {
+ try_epsv = 0;
+ result = command(pasvcmd = "LPSV");
+ }
+ break;
+#endif
+ default:
+ result = COMPLETE + 1;
+ break;
+ }
+ if (result != COMPLETE) {
+ printf("Passive mode refused.\n");
+ goto bad;
+ }
+
+#define pack2(var) \
+ (((var[0] & 0xff) << 8) | ((var[1] & 0xff) << 0))
+#define pack4(var) \
+ ((((var)[0] & 0xff) << 24) | (((var)[1] & 0xff) << 16) | \
+ (((var)[2] & 0xff) << 8) | (((var)[3] & 0xff) << 0))
+
+ /*
+ * What we've got at this point is a string of comma separated
+ * one-byte unsigned integer values, separated by commas.
+ */
+ error = 0;
+ if (strcmp(pasvcmd, "PASV") == 0) {
+ if (data_addr.su_family != AF_INET) {
+ error = 2;
+ goto psv_done;
+ }
+ if (code / 10 == 22 && code != 227) {
+ error = 227;
+ goto psv_done;
+ }
+ if (sscanf(pasv, "%u,%u,%u,%u,%u,%u",
+ &ad[0], &ad[1], &ad[2], &ad[3],
+ &po[0], &po[1]) != 6) {
+ error = 1;
+ goto psv_done;
+ }
+ data_addr.su_sin.sin_addr.s_addr = htonl(pack4(ad));
+ data_addr.su_port = htons(pack2(po));
+ } else
+ if (strcmp(pasvcmd, "LPSV") == 0) {
+ if (code / 10 == 22 && code != 228) {
+ error = 228;
+ goto psv_done;
+ }
+ switch (data_addr.su_family) {
+ case AF_INET:
+ if (sscanf(pasv, "%u,%u,%u,%u,%u,%u,%u,%u,%u",
+ &af, &alen,
+ &ad[0], &ad[1], &ad[2], &ad[3],
+ &plen, &po[0], &po[1]) != 9) {
+ error = 1;
+ goto psv_done;
+ }
+ if (af != 4 || alen != 4 || plen != 2) {
+ error = 2;
+ goto psv_done;
+ }
+ data_addr.su_sin.sin_addr.s_addr =
+ htonl(pack4(ad));
+ data_addr.su_port = htons(pack2(po));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (sscanf(pasv,
+ "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
+ &af, &alen,
+ &ad[0], &ad[1], &ad[2], &ad[3],
+ &ad[4], &ad[5], &ad[6], &ad[7],
+ &ad[8], &ad[9], &ad[10], &ad[11],
+ &ad[12], &ad[13], &ad[14], &ad[15],
+ &plen, &po[0], &po[1]) != 21) {
+ error = 1;
+ goto psv_done;
+ }
+ if (af != 6 || alen != 16 || plen != 2) {
+ error = 2;
+ goto psv_done;
+ }
+ data_addr.su_sin6.sin6_addr.s6_addr32[0] =
+ htonl(pack4(ad));
+ data_addr.su_sin6.sin6_addr.s6_addr32[1] =
+ htonl(pack4(ad+4));
+ data_addr.su_sin6.sin6_addr.s6_addr32[2] =
+ htonl(pack4(ad+8));
+ data_addr.su_sin6.sin6_addr.s6_addr32[3] =
+ htonl(pack4(ad+12));
+ data_addr.su_port = htons(pack2(po));
+ break;
+#endif
+ default:
+ error = 1;
+ }
+ } else if (strncmp(pasvcmd, "EPSV", 4) == 0) {
+ char delim[4];
+ u_int epsvpo;
+
+ if (code / 10 == 22 && code != 229) {
+ error = 229;
+ goto psv_done;
+ }
+ if (sscanf(pasv, "%c%c%c%u%c", &delim[0], &delim[1],
+ &delim[2], &epsvpo, &delim[3]) != 5) {
+ error = 1;
+ goto psv_done;
+ }
+ if (delim[0] != delim[1] || delim[0] != delim[2]
+ || delim[0] != delim[3]) {
+ error = 1;
+ goto psv_done;
+ }
+ data_addr.su_port = htons(epsvpo);
+ } else {
+ error = 1;
+ }
+psv_done:
+ switch (error) {
+ case 0:
+ break;
+ case 1:
+ fprintf(stderr,
+ "Passive mode address scan failure. Shouldn't happen!\n");
+ goto bad;
+ case 2:
+ fprintf(stderr,
+ "Passive mode AF mismatch. Shouldn't happen!\n");
+ goto bad;
+ case 227:
+ case 228:
+ case 229:
+ fprintf(stderr,
+ "wrong server: return code must be %d\n", error);
+ goto bad;
+ default:
+ fprintf(stderr, "Bug\n");
+ }
+
+ if (connect(data, (struct sockaddr *) &data_addr,
+ (data_addr.su_family == AF_INET ?
+ sizeof(data_addr.su_sin) :
+ sizeof(data_addr.su_sin6)))<0) {
+ perror("ftp: connect");
+ return(1);
+ }
+#ifdef IP_TOS
+ if (data_addr.su_family == AF_INET)
+ {
+ tos = IPTOS_THROUGHPUT;
+ if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&tos,
+ sizeof(tos)) < 0)
+ perror("ftp: setsockopt TOS (ignored)");
+ }
+#endif
+ return(0);
+ }
+noport:
+ data_addr = myctladdr;
+ if (sendport)
+ data_addr.su_port = 0; /* let system pick one */
+ if (data != -1)
+ (void) close(data);
+ data = socket(data_addr.su_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ perror("ftp: socket");
+ if (tmpno)
+ sendport = 1;
+ return (1);
+ }
+ if (!sendport)
+ if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
+ perror("ftp: setsockopt (reuse address)");
+ goto bad;
+ }
+ if (setsockopt (data, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+ sizeof(timeout)) < 0) {
+ perror("ftp: setsockopt failed\n");
+ }
+ if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
+ perror("ftp: bind");
+ goto bad;
+ }
+ if (options & SO_DEBUG &&
+ setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
+ perror("ftp: setsockopt (ignored)");
+ len = sizeof (data_addr);
+ if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
+ perror("ftp: getsockname");
+ goto bad;
+ }
+ if (listen(data, 1) < 0)
+ perror("ftp: listen");
+ if (sendport) {
+ af = ex_af2prot(data_addr.su_family);
+ if (try_eprt && af > 1) { /* only IPv6 */
+ if (getnameinfo((struct sockaddr *)&data_addr, len,
+ hbuf, sizeof(hbuf), pbuf, sizeof(pbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
+ result = command("EPRT |%d|%s|%s|",
+ af, hbuf, pbuf);
+ if (result != COMPLETE) {
+ try_eprt = 0;
+ }
+ } else {
+ result = ERROR;
+ }
+ } else {
+ result = COMPLETE + 1;
+ }
+ if (result == COMPLETE)
+ goto prt_done;
+
+ p = (u_char *)&data_addr.su_port;
+ switch (data_addr.su_family) {
+ case AF_INET:
+ a = (u_char *)&data_addr.su_sin.sin_addr;
+ result = command("PORT %u,%u,%u,%u,%u,%u",
+ a[0], a[1], a[2], a[3], p[0], p[1]);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ a = (u_char *)&data_addr.su_sin6.sin6_addr;
+ result = command(
+ "LPRT 6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,2,%d,%d",
+ a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7],
+ a[8], a[9],a[10],a[11],a[12],a[13],a[14],a[15],
+ p[0], p[1]);
+ break;
+#endif
+ default:
+ result = COMPLETE + 1; /* xxx */
+ }
+
+ prt_done:
+ if (result == ERROR && sendport == -1) {
+ sendport = 0;
+ tmpno = 1;
+ goto noport;
+ }
+ return (result != COMPLETE);
+ }
+ if (tmpno)
+ sendport = 1;
+#ifdef IP_TOS
+ if (data_addr.su_family == AF_INET)
+ {
+ on = IPTOS_THROUGHPUT;
+ if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+ perror("ftp: setsockopt TOS (ignored)");
+ }
+#endif
+ return (0);
+bad:
+ (void) close(data), data = -1;
+ if (tmpno)
+ sendport = 1;
+ return (1);
+}
+
+static FILE *
+dataconn(const char *lmode)
+{
+ union sockunion from;
+ int s, tos;
+ socklen_t fromlen = sizeof(from);
+
+ if (passivemode)
+ return (fdopen(data, lmode));
+
+ s = accept(data, (struct sockaddr *) &from, &fromlen);
+ if (s < 0) {
+ perror("ftp: accept");
+ (void) close(data), data = -1;
+ return (NULL);
+ }
+ (void) close(data);
+ data = s;
+#ifdef IP_TOS
+ if (from.su_family == AF_INET)
+ {
+ tos = IPTOS_THROUGHPUT;
+ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+ perror("ftp: setsockopt TOS (ignored)");
+ }
+#endif
+ return (fdopen(data, lmode));
+}
+
+static void
+ptransfer(const char *direction, long long bytes,
+ const struct timeval *t0,
+ const struct timeval *t1)
+{
+ struct timeval td;
+ float s, bs;
+
+ if (verbose) {
+ tvsub(&td, t1, t0);
+ s = td.tv_sec + (td.tv_usec / 1000000.);
+#define nz(x) ((x) == 0 ? 1 : (x))
+ bs = bytes / nz(s);
+ printf("%lld bytes %s in %.3g secs (%.2f Kbytes/sec)\n",
+ bytes, direction, s, bs / 1000.0);
+ }
+}
+
+#if 0
+tvadd(tsum, t0)
+ struct timeval *tsum, *t0;
+{
+
+ tsum->tv_sec += t0->tv_sec;
+ tsum->tv_usec += t0->tv_usec;
+ if (tsum->tv_usec > 1000000)
+ tsum->tv_sec++, tsum->tv_usec -= 1000000;
+}
+#endif
+
+static void
+tvsub(struct timeval *tdiff,
+ const struct timeval *t1,
+ const struct timeval *t0)
+{
+
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0)
+ 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];
+ union sockunion mctl;
+ union sockunion hctl;
+ FILE *in;
+ FILE *out;
+ int tpe;
+ int curtpe;
+ int cpnd;
+ int sunqe;
+ int runqe;
+ int mcse;
+ int ntflg;
+ char nti[NTRANS_MAX+1];
+ char nto[NTRANS_MAX+1];
+ int mapflg;
+ char mi[MAXPATHLEN];
+ char mo[MAXPATHLEN];
+ } proxstruct, tmpstruct;
+ struct comvars *ip, *op;
+
+ abrtflag = 0;
+ oldintr = signal(SIGINT, psabort);
+ if (flag) {
+ if (proxy)
+ return;
+ ip = &tmpstruct;
+ op = &proxstruct;
+ proxy++;
+ }
+ else {
+ if (!proxy)
+ return;
+ ip = &proxstruct;
+ op = &tmpstruct;
+ proxy = 0;
+ }
+ ip->connect = connected;
+ connected = op->connect;
+ if (hostname) {
+ (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
+ ip->name[sizeof(ip->name) - 1] = '\0';
+ }
+ else {
+ ip->name[0] = 0;
+ }
+ hostname = op->name;
+ ip->hctl = hisctladdr;
+ hisctladdr = op->hctl;
+ ip->mctl = myctladdr;
+ myctladdr = op->mctl;
+ ip->in = cin;
+ cin = op->in;
+ ip->out = cout;
+ cout = op->out;
+ ip->tpe = type;
+ type = op->tpe;
+ ip->curtpe = curtype;
+ curtype = op->curtpe;
+ ip->cpnd = cpend;
+ cpend = op->cpnd;
+ ip->sunqe = sunique;
+ sunique = op->sunqe;
+ ip->runqe = runique;
+ runique = op->runqe;
+ ip->mcse = mcase;
+ mcase = op->mcse;
+ ip->ntflg = ntflag;
+ ntflag = op->ntflg;
+ (void) strncpy(ip->nti, ntin, NTRANS_MAX);
+ (ip->nti)[NTRANS_MAX] = '\0'; /* shouldn't use strlen */
+ (void) strcpy(ntin, op->nti);
+ (void) strncpy(ip->nto, ntout, NTRANS_MAX);
+ (ip->nto)[NTRANS_MAX] = '\0';
+ (void) strcpy(ntout, op->nto);
+ ip->mapflg = mapflag;
+ mapflag = op->mapflg;
+ (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
+ (ip->mi)[MAXPATHLEN - 1] = '\0';
+ (void) strcpy(mapin, op->mi);
+ (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
+ (ip->mo)[MAXPATHLEN - 1] = '\0';
+ (void) strcpy(mapout, op->mo);
+ (void) signal(SIGINT, oldintr);
+ if (abrtflag) {
+ abrtflag = 0;
+ (*oldintr)(SIGINT);
+ }
+}
+
+static
+void
+abortpt(int ignore)
+{
+ (void)ignore;
+ printf("\n");
+ 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;
+
+ if (strcmp(cmd, "RETR"))
+ cmd2 = "RETR";
+ else
+ cmd2 = runique ? "STOU" : "STOR";
+ if ((prox_type = type) == 0) {
+ if (unix_server && unix_proxy)
+ prox_type = TYPE_I;
+ else
+ prox_type = TYPE_A;
+ }
+ if (curtype != prox_type)
+ changetype(prox_type, 1);
+ if (command("PASV") != COMPLETE) {
+ printf("proxy server does not support third party transfers.\n");
+ return;
+ }
+ pswitch(0);
+ if (!connected) {
+ printf("No primary connection\n");
+ pswitch(1);
+ code = -1;
+ return;
+ }
+ if (curtype != prox_type)
+ changetype(prox_type, 1);
+ if (command("PORT %s", pasv) != COMPLETE) {
+ pswitch(1);
+ return;
+ }
+ if (sigsetjmp(ptabort, 1))
+ goto abort;
+ oldintr = signal(SIGINT, abortpt);
+ if (command("%s %s", cmd, remote) != PRELIM) {
+ (void) signal(SIGINT, oldintr);
+ pswitch(1);
+ return;
+ }
+ sleep(2);
+ pswitch(1);
+ secndflag++;
+ if (command("%s %s", cmd2, local) != PRELIM)
+ goto abort;
+ ptflag++;
+ (void) getreply(0);
+ pswitch(0);
+ (void) getreply(0);
+ (void) signal(SIGINT, oldintr);
+ pswitch(1);
+ ptflag = 0;
+ printf("local: %s remote: %s\n", local, remote);
+ return;
+abort:
+ (void) signal(SIGINT, SIG_IGN);
+ ptflag = 0;
+ if (strcmp(cmd, "RETR") && !proxy)
+ pswitch(1);
+ else if (!strcmp(cmd, "RETR") && proxy)
+ pswitch(0);
+ if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
+ if (command("%s %s", cmd2, local) != PRELIM) {
+ pswitch(0);
+ if (cpend)
+ abort_remote((FILE *) NULL);
+ }
+ pswitch(1);
+ if (ptabflg)
+ code = -1;
+ (void) signal(SIGINT, oldintr);
+ return;
+ }
+ if (cpend)
+ abort_remote((FILE *) NULL);
+ pswitch(!proxy);
+ if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
+ if (command("%s %s", cmd2, local) != PRELIM) {
+ pswitch(0);
+ if (cpend)
+ abort_remote((FILE *) NULL);
+ pswitch(1);
+ if (ptabflg)
+ code = -1;
+ (void) signal(SIGINT, oldintr);
+ return;
+ }
+ }
+ if (cpend)
+ abort_remote((FILE *) NULL);
+ pswitch(!proxy);
+ if (cpend) {
+ FD_ZERO(&mask);
+ FD_SET(fileno(cin), &mask);
+ if ((nfnd = empty(&mask, fileno(cin), 10)) <= 0) {
+ if (nfnd < 0) {
+ perror("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer(0);
+ if(cout != NULL)
+ {
+ fclose(cout);
+ cout = NULL;
+ }
+ }
+ (void) getreply(0);
+ (void) getreply(0);
+ }
+ if (proxy)
+ pswitch(0);
+ pswitch(1);
+ if (ptabflg)
+ code = -1;
+ (void) signal(SIGINT, oldintr);
+}
+
+void
+reset(void)
+{
+ fd_set mask;
+ int nfnd = 1;
+
+ FD_ZERO(&mask);
+ while (nfnd > 0) {
+ FD_SET(fileno(cin), &mask);
+ if ((nfnd = empty(&mask, fileno(cin), 0)) < 0) {
+ perror("reset");
+ code = -1;
+ lostpeer(0);
+ if(cout != NULL)
+ {
+ fclose(cout);
+ cout = NULL;
+ }
+ }
+ else if (nfnd) {
+ (void) getreply(0);
+ }
+ }
+}
+
+static char *
+gunique(char *local)
+{
+ static char new[MAXPATHLEN];
+ char *cp = rindex(local, '/');
+ int d, count=0;
+ char ext = '1';
+
+ if (cp)
+ *cp = '\0';
+ d = access(cp ? local : ".", W_OK);
+ if (cp)
+ *cp = '/';
+ if (d < 0) {
+ fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
+ return((char *) 0);
+ }
+ (void) strcpy(new, local);
+ cp = new + strlen(new);
+ *cp++ = '.';
+ while (!d) {
+ if (++count == 100) {
+ printf("runique: can't find unique file name.\n");
+ return((char *) 0);
+ }
+ *cp++ = ext;
+ *cp = '\0';
+ if (ext == '9')
+ ext = '0';
+ else
+ ext++;
+ if ((d = access(new, F_OK)) < 0)
+ break;
+ if (ext != '0')
+ cp--;
+ else if (*(cp - 2) == '.')
+ *(cp - 1) = '1';
+ else {
+ *(cp - 2) = *(cp - 2) + 1;
+ cp--;
+ }
+ }
+ return(new);
+}
+
+static void
+abort_remote(FILE *din)
+{
+ char buf[BUFSIZ];
+ int nfnd, hifd;
+ 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);
+ FD_ZERO(&mask);
+ 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 (nfnd < 0) {
+ perror("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer(0);
+ if(cout != NULL)
+ {
+ fclose(cout);
+ cout = NULL;
+ }
+ }
+ if (din && FD_ISSET(fileno(din), &mask)) {
+ while (read(fileno(din), buf, BUFSIZ) > 0)
+ /* LOOP */;
+ }
+ if (getreply(0) == ERROR && code == 552) {
+ /* 552 needed for nic style abort */
+ (void) getreply(0);
+ }
+ (void) getreply(0);
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp_var.h
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp_var.h (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/ftp_var.h (revision 5)
@@ -0,0 +1,167 @@
+/* $USAGI$ */
+
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ * from: @(#)ftp_var.h 5.9 (Berkeley) 6/1/90
+ * $Id: ftp_var.h,v 1.3 2001/01/12 21:36:27 sekiya Exp $
+ */
+
+/*
+ * FTP global variables.
+ */
+
+#include <setjmp.h>
+#include <sys/param.h>
+#define NTRANS_MAX 64
+
+/*
+ * Tick counter step size.
+ */
+#define TICKBYTES 10240
+
+#ifndef Extern
+#define Extern extern
+#endif
+
+#define LINELEN PATH_MAX+200
+
+/*
+ * Options and other state info.
+ */
+Extern int rl_inhibit; /* disable readline support */
+Extern int traceflag; /* trace packets exchanged */
+Extern int hash; /* print # for each buffer transferred */
+Extern int tick; /* print byte counter during transfers */
+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 fromatty; /* input is from a terminal */
+Extern int interactive; /* interactively prompt on m* cmds */
+Extern int debug; /* debugging level */
+Extern int bell; /* ring bell on cmd completion */
+Extern int doglob; /* glob local file names */
+Extern int autologin; /* establish user account on connection */
+Extern int multihome; /* multi homed host, use same interface for cmd and data channels */
+Extern int proxy; /* proxy server connection active */
+Extern int proxflag; /* proxy connection exists */
+Extern int sunique; /* store files on server with unique name */
+Extern int runique; /* store local files with unique name */
+Extern int mcase; /* map upper to lower case for mget names */
+Extern int ntflag; /* use ntin ntout tables for name xlation */
+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 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 */
+Extern char ntin[NTRANS_MAX+1]; /* input translation table */
+Extern char ntout[NTRANS_MAX+1]; /* output translation table */
+Extern char mapin[MAXPATHLEN]; /* input map template */
+Extern char mapout[MAXPATHLEN]; /* output map template */
+Extern char typename[32]; /* name of file transfer type */
+Extern int type; /* requested file transfer type */
+Extern int curtype; /* current file transfer type */
+Extern char structname[32]; /* name of file transfer structure */
+Extern int stru; /* file transfer structure */
+Extern char formname[32]; /* name of file transfer format */
+Extern int form; /* file transfer format */
+Extern char modename[32]; /* name of file transfer mode */
+Extern int mode; /* file transfer mode */
+Extern char bytename[32]; /* local byte size in ascii */
+Extern int bytesize; /* local byte size in binary */
+
+Extern char *hostname; /* name of host connected to */
+Extern int unix_server; /* server is unix, can use binary for ascii */
+Extern int unix_proxy; /* proxy is unix, can use binary for ascii */
+
+/*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 char line[LINELEN]; /* input line buffer */
+Extern char *stringbase; /* current scan point in line buffer */
+Extern char argbuf[LINELEN]; /* 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 */
+
+Extern int options; /* used during socket creation */
+Extern int try_epsv; /* try EPSV for this session */
+Extern int try_eprt; /* try EPRT for this session */
+
+/*
+ * Format of command table.
+ */
+struct cmd {
+ const char *c_name; /* name of command */
+ const char *c_help; /* help string */
+ char c_bell; /* give bell when command completes */
+ char c_conn; /* must be connected to use command */
+ char c_proxy; /* proxy server may execute */
+
+ /* Exactly one of these should be non-NULL. */
+ void (*c_handler_v)(int, char **); /* function to call */
+ void (*c_handler_0)(void);
+ void (*c_handler_1)(const char *);
+};
+
+struct macel {
+ char mac_name[9]; /* macro name */
+ char *mac_start; /* start of macro in macbuf */
+ char *mac_end; /* end of macro in macbuf */
+};
+
+Extern int macnum; /* number of defined macros */
+Extern struct macel macros[16];
+Extern char macbuf[4096];
+#define MACBUF_SIZE 4096
+
+char *hookup(const char *host, const char *port);
+struct cmd *getcmd(const char *);
+char **makeargv(int *pargc, char **parg);
+int dologin(const char *host);
+int command(const char *fmt, ...);
+void sendrequest(const char *cmd, char *local, char *remote, int printnames);
+void recvrequest(const char *cmd, char *local, char *remote,
+ const char *lmode, int printnames);
+int another(int *pargc, char ***pargv, const char *prompt);
+void blkfree(char **av0);
+void fatal(const char *msg);
+int getreply(int expecteof);
+void domacro(int argc, char *argv[]);
+void pswitch(int flag);
+int xruserpass(const char *host, char **aname, char **apass, char **aacct);
+void setpeer(int argc, char *argv[]);
+void quit(void);
+void changetype(int newtype, int show);
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/glob.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/glob.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/glob.c (revision 5)
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * From: @(#)glob.c 5.9 (Berkeley) 2/25/91
+ */
+char glob_rcsid[] =
+ "$Id: glob.c,v 1.9 1999/10/02 13:25:23 netbug Exp $";
+
+/*
+ * C-shell glob for random programs.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ftp_var.h" /* for protos only */
+#include "glob.h"
+
+#define QUOTE 0200
+#define TRIM 0177
+#define eq(a,b) (strcmp(a, b)==0)
+#define GAVSIZ (sysconf(_SC_ARG_MAX)/6)
+#define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
+
+const char *globerr;
+extern const char *home;
+
+typedef struct {
+ const char *text;
+} centry;
+
+typedef struct {
+ char *text;
+} entry;
+
+static entry *gargv; /* Pointer to the (stack) arglist */
+static entry *sortbas;
+static int gargc; /* Number args in gargv */
+static int gnleft; /* space left before we hit max args length */
+
+static short gflag;
+
+static int globcnt;
+static const char *globchars = "`{[*?";
+
+static char *gpath;
+static char *gpathp, *lastgpathp;
+static int globbed;
+static const char *entp;
+
+static int tglob(char c);
+static char *strspl(const char *, const char *);
+static char *strend(char *);
+static char **copyblk(entry *);
+static char **cloneblk(const centry *);
+
+static void addpath(char c);
+static void acollect(const char *);
+static void collect(const char *);
+static void expand(const char *);
+static void Gcat(const char *, const char *);
+static void ginit(entry *);
+static void matchdir(const char *);
+static void rscan(centry *, int (*f)(char));
+static void sort(void);
+static void efree(entry *);
+static int amatch(const char *, const char *);
+static int execbrc(const char *, const char *);
+static int match(const char *, const char *);
+
+static int gethdir(char *homedir);
+static int letter(char c);
+static int digit(char c);
+static int any(int c, const char *s);
+
+char **
+ftpglob(const char *v)
+{
+ char agpath[BUFSIZ];
+ entry *agargv;
+ centry vv[2];
+ vv[0].text = v;
+ vv[1].text = NULL;
+ gflag = 0;
+ rscan(vv, tglob);
+ if (gflag == 0) {
+ return cloneblk(vv);
+ }
+
+ globerr = 0;
+
+ gpath = agpath;
+ gpathp = gpath;
+ *gpathp = 0;
+ /* added ()'s to sizeof, (ambigious math for the compiler) */
+ lastgpathp = agpath + (sizeof(agpath)- 2);
+
+ agargv = (entry *)malloc(sizeof (entry) * GAVSIZ);
+ if (agargv == NULL) fatal("Out of memory");
+ ginit(agargv);
+ globcnt = 0;
+ collect(v);
+ if (globcnt == 0 && (gflag&1)) {
+ efree(gargv);
+ gargv = NULL;
+ return NULL;
+ }
+ else {
+ char **rv = copyblk(gargv);
+ gargv = NULL;
+ return rv;
+ }
+}
+
+static
+void
+ginit(entry *agargv)
+{
+ agargv[0].text = NULL;
+ gargv = agargv;
+ sortbas = agargv;
+ gargc = 0;
+ gnleft = sysconf(_SC_ARG_MAX) - 4;
+}
+
+static
+void
+collect(const char *as)
+{
+ if (eq(as, "{") || eq(as, "{}")) {
+ Gcat(as, "");
+ sort();
+ }
+ else {
+ acollect(as);
+ }
+}
+
+static
+void
+acollect(const char *as)
+{
+ int ogargc = gargc;
+
+ gpathp = gpath; *gpathp = 0; globbed = 0;
+ expand(as);
+ if (gargc != ogargc)
+ sort();
+}
+
+static
+void
+sort(void)
+{
+ entry *p1, *p2, c;
+ entry *Gvp = &gargv[gargc];
+
+ p1 = sortbas;
+ while (p1 < Gvp-1) {
+ p2 = p1;
+ while (++p2 < Gvp)
+ if (strcmp(p1->text, p2->text) > 0)
+ c = *p1, *p1 = *p2, *p2 = c;
+ p1++;
+ }
+ sortbas = Gvp;
+}
+
+static
+void
+expand(const char *as)
+{
+ const char *cs;
+ const char *oldcs;
+ char *sgpathp;
+ struct stat stb;
+
+ sgpathp = gpathp;
+ cs = as;
+ if (*cs == '~' && gpathp == gpath) {
+ addpath('~');
+ for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
+ addpath(*cs++);
+ if (!*cs || *cs == '/') {
+ if (gpathp != gpath + 1) {
+ *gpathp = 0;
+ if (gethdir(gpath + 1))
+ globerr = "Unknown user name after ~";
+ /*
+ * Was: strcpy(gpath, gpath + 1);
+ * but that's WRONG
+ */
+ memmove(gpath, gpath+1, strlen(gpath+1)+1);
+ }
+ else {
+ (void) strcpy(gpath, home);
+ }
+ gpathp = strend(gpath);
+ }
+ }
+ while (!any(*cs, globchars)) {
+ if (*cs == 0) {
+ if (!globbed)
+ Gcat(gpath, "");
+ else if (stat(gpath, &stb) >= 0) {
+ Gcat(gpath, "");
+ globcnt++;
+ }
+ goto endit;
+ }
+ addpath(*cs++);
+ }
+ oldcs = cs;
+ while (cs > as && *cs != '/')
+ cs--, gpathp--;
+ if (*cs == '/')
+ cs++, gpathp++;
+ *gpathp = 0;
+ if (*oldcs == '{') {
+ (void) execbrc(cs, ((char *)0));
+ return;
+ }
+ matchdir(cs);
+endit:
+ gpathp = sgpathp;
+ *gpathp = 0;
+}
+
+static
+void
+matchdir(const char *pattern)
+{
+ struct stat stb;
+ register struct dirent *dp;
+ DIR *dirp;
+
+#if 0
+#ifdef __linux__
+ if (gpath == NULL || *gpath == '\0')
+ gpath = "./";
+#endif
+#endif
+ dirp = opendir((!gpath || !*gpath) ? "./" : gpath);
+ if (dirp == NULL) {
+ if (globbed)
+ return;
+ goto patherr2;
+ }
+ if (fstat(dirfd(dirp), &stb) < 0)
+ goto patherr1;
+ if (!isdir(stb)) {
+ errno = ENOTDIR;
+ goto patherr1;
+ }
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_ino == 0)
+ continue;
+ if (match(dp->d_name, pattern)) {
+ Gcat(gpath, dp->d_name);
+ globcnt++;
+ }
+ }
+ closedir(dirp);
+ return;
+
+patherr1:
+ closedir(dirp);
+patherr2:
+ globerr = "Bad directory components";
+}
+
+static
+int
+execbrc(const char *p, const char *s)
+{
+ char restbuf[BUFSIZ + 2];
+ const char *pe, *pm, *pl;
+ int brclev = 0;
+ char *lm, *sgpathp;
+
+ for (lm = restbuf; *p != '{'; *lm++ = *p++)
+ continue;
+ for (pe = ++p; *pe; pe++)
+ switch (*pe) {
+
+ case '{':
+ brclev++;
+ continue;
+
+ case '}':
+ if (brclev == 0)
+ goto pend;
+ brclev--;
+ continue;
+
+ case '[':
+ for (pe++; *pe && *pe != ']'; pe++)
+ continue;
+ continue;
+ }
+pend:
+ brclev = 0;
+ for (pl = pm = p; pm <= pe; pm++)
+ switch (*pm & (QUOTE|TRIM)) {
+
+ case '{':
+ brclev++;
+ continue;
+
+ case '}':
+ if (brclev) {
+ brclev--;
+ continue;
+ }
+ goto doit;
+
+ case ','|QUOTE:
+ case ',':
+ if (brclev)
+ continue;
+doit:
+#if 0
+ savec = *pm;
+ *pm = 0;
+ strcpy(lm, pl);
+ *pm = savec;
+#else
+ strncpy(lm, pl, pm-pl);
+ lm[pm-pl] = 0;
+#endif
+ (void) strcat(restbuf, pe + 1);
+ if (s == 0) {
+ sgpathp = gpathp;
+ expand(restbuf);
+ gpathp = sgpathp;
+ *gpathp = 0;
+ }
+ else if (amatch(s, restbuf)) {
+ return (1);
+ }
+ sort();
+ pl = pm + 1;
+ if (brclev)
+ return (0);
+ continue;
+
+ case '[':
+ for (pm++; *pm && *pm != ']'; pm++)
+ continue;
+ if (!*pm)
+ pm--;
+ continue;
+ }
+ if (brclev)
+ goto doit;
+ return (0);
+}
+
+static
+int
+match(const char *s, const char *p)
+{
+ int c;
+ const char *sentp;
+ char sglobbed = globbed;
+
+ if (*s == '.' && *p != '.')
+ return (0);
+ sentp = entp;
+ entp = s;
+ c = amatch(s, p);
+ entp = sentp;
+ globbed = sglobbed;
+ return (c);
+}
+
+static
+int
+amatch(const char *s, const char *p)
+{
+ register int scc;
+ int ok, lc;
+ char *sgpathp;
+ struct stat stb;
+ int c, cc;
+
+ globbed = 1;
+ for (;;) {
+ scc = *s++ & TRIM;
+ switch (c = *p++) {
+
+ case '{':
+ return (execbrc(p - 1, s - 1));
+
+ case '[':
+ ok = 0;
+ lc = 077777;
+ while ((cc = *p++) != 0) {
+ if (cc == ']') {
+ if (ok)
+ break;
+ return (0);
+ }
+ if (cc == '-') {
+ if (lc <= scc && scc <= *p++)
+ ok++;
+ } else
+ if (scc == (lc = cc))
+ ok++;
+ }
+ if (cc == 0) {
+ if (ok)
+ p--;
+ else
+ return 0;
+ }
+ continue;
+
+ case '*':
+ if (!*p)
+ return (1);
+ if (*p == '/') {
+ p++;
+ goto slash;
+ }
+ s--;
+ do {
+ if (amatch(s, p))
+ return (1);
+ } while (*s++);
+ return (0);
+
+ case 0:
+ return (scc == 0);
+
+ default:
+ if (c != scc)
+ return (0);
+ continue;
+
+ case '?':
+ if (scc == 0)
+ return (0);
+ continue;
+
+ case '/':
+ if (scc)
+ return (0);
+slash:
+ s = entp;
+ sgpathp = gpathp;
+ while (*s)
+ addpath(*s++);
+ addpath('/');
+ if (stat(gpath, &stb) == 0 && isdir(stb)) {
+ if (*p == 0) {
+ Gcat(gpath, "");
+ globcnt++;
+ } else {
+ expand(p);
+ }
+ }
+ gpathp = sgpathp;
+ *gpathp = 0;
+ return (0);
+ }
+ }
+}
+
+#if 0 /* dead code */
+static
+int
+Gmatch(const char *s, const char *p)
+{
+ register int scc;
+ int ok, lc;
+ int c, cc;
+
+ for (;;) {
+ scc = *s++ & TRIM;
+ switch (c = *p++) {
+
+ case '[':
+ ok = 0;
+ lc = 077777;
+ while ((cc = *p++) != 0) {
+ if (cc == ']') {
+ if (ok)
+ break;
+ return (0);
+ }
+ if (cc == '-') {
+ if (lc <= scc && scc <= *p++)
+ ok++;
+ } else
+ if (scc == (lc = cc))
+ ok++;
+ }
+ if (cc == 0)
+ if (ok)
+ p--;
+ else
+ return 0;
+ continue;
+
+ case '*':
+ if (!*p)
+ return (1);
+ for (s--; *s; s++)
+ if (Gmatch(s, p))
+ return (1);
+ return (0);
+
+ case 0:
+ return (scc == 0);
+
+ default:
+ if ((c & TRIM) != scc)
+ return (0);
+ continue;
+
+ case '?':
+ if (scc == 0)
+ return (0);
+ continue;
+
+ }
+ }
+}
+#endif
+
+static
+void
+Gcat(const char *s1, const char *s2)
+{
+ int len = strlen(s1) + strlen(s2) + 1;
+
+ if (len >= gnleft || gargc >= GAVSIZ - 1) {
+ globerr = "Arguments too long";
+ }
+ else {
+ gargc++;
+ gnleft -= len;
+ gargv[gargc].text = NULL;
+ gargv[gargc - 1].text = strspl(s1, s2);
+ }
+}
+
+static
+void
+addpath(char c)
+{
+
+ if (gpathp >= lastgpathp)
+ globerr = "Pathname too long";
+ else {
+ *gpathp++ = c;
+ *gpathp = 0;
+ }
+}
+
+static void
+rscan(centry *t, int (*f)(char))
+{
+ const char *p;
+ char c;
+
+ while ((p = (t++)->text) != NULL) {
+ if (f == tglob) {
+ if (*p == '~')
+ gflag |= 2;
+ else if (eq(p, "{") || eq(p, "{}"))
+ continue;
+ }
+ while ((c = *p++) != 0)
+ (*f)(c);
+ }
+}
+
+static
+int
+tglob(char c)
+{
+
+ if (any(c, globchars))
+ gflag |= c == '{' ? 2 : 1;
+ return (c);
+}
+
+static int
+letter(char c)
+{
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
+}
+
+static int
+digit(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+static
+int
+any(int c, const char *s)
+{
+ while (*s) if (*s++ == c) return 1;
+ return 0;
+}
+
+static
+int
+cblklen(const centry *av)
+{
+ int i = 0;
+ while ((av++)->text) i++;
+ return i;
+}
+
+static
+int
+blklen(const entry *av)
+{
+ int i = 0;
+ while ((av++)->text) i++;
+ return i;
+}
+
+void
+blkfree(char **av)
+{
+ int i;
+ for (i=0; av[i]; i++) free(av[i]);
+}
+
+static
+void
+efree(entry *av)
+{
+ int i;
+ for (i=0; av[i].text; i++) free(av[i].text);
+ free((void *)av);
+}
+
+static
+char *
+strspl(const char *cp, const char *dp)
+{
+ char *ep = malloc(strlen(cp) + strlen(dp) + 1);
+ if (ep == NULL) fatal("Out of memory");
+
+ strcpy(ep, cp);
+ strcat(ep, dp);
+ return ep;
+}
+
+static
+char **
+copyblk(entry *v)
+{
+ int i;
+ char **nv = malloc((blklen(v) + 1) * sizeof(char **));
+ if (nv == NULL) fatal("Out of memory");
+
+ for (i=0; v[i].text; i++) {
+ nv[i] = v[i].text;
+ v[i].text = NULL;
+ }
+ nv[i] = NULL;
+
+ return nv;
+}
+
+static
+char **
+cloneblk(const centry *v)
+{
+ int i;
+ char **nv = malloc((cblklen(v) + 1) * sizeof(char **));
+ if (nv == NULL) fatal("Out of memory");
+
+ for (i=0; v[i].text; i++) {
+ nv[i] = strdup(v[i].text);
+ }
+ nv[i] = NULL;
+
+ return nv;
+}
+
+static
+char *
+strend(char *cp)
+{
+ while (*cp)
+ cp++;
+ return (cp);
+}
+/*
+ * Extract a home directory from the password file
+ * The argument points to a buffer where the name of the
+ * user whose home directory is sought is currently.
+ * We write the home directory of the user back there.
+ *
+ * XXX, this needs buffer length checking and stuff.
+ */
+static
+int
+gethdir(char *homedir)
+{
+ register struct passwd *pp = getpwnam(homedir);
+
+ if (!pp || homedir + strlen(pp->pw_dir) >= lastgpathp)
+ return 1;
+ strcpy(homedir, pp->pw_dir);
+ return 0;
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/main.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/main.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/main.c (revision 5)
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 1985, 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+char copyright[] =
+ "@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n"
+ "All rights reserved.\n";
+
+/*
+ * from: @(#)main.c 5.18 (Berkeley) 3/1/91
+ */
+char main_rcsid[] =
+ "$Id: main.c,v 1.15 1999/10/02 13:25:23 netbug Exp $";
+
+
+/*
+ * FTP User Program -- Command Interface.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+/* #include <arpa/ftp.h> <--- unused? */
+
+#include <locale.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <pwd.h>
+#ifdef __USE_READLINE__
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
+#define Extern
+#include "ftp_var.h"
+int traceflag = 0;
+const char *home = "/";
+
+extern FILE *cout;
+extern int data;
+extern struct cmd cmdtab[];
+extern int NCMDS;
+
+void intr(int);
+void lostpeer(int);
+void help(int argc, char *argv[]);
+
+static void cmdscanner(int top);
+static char *slurpstring(void);
+
+static
+void
+usage(void)
+{
+ printf("\n\tUsage: { ftp | pftp } [-Apinegvtd] [hostname]\n");
+ printf("\t -A: enable active mode\n");
+ printf("\t -p: enable passive mode (default for ftp and pftp)\n");
+ printf("\t -i: turn off prompting during mget\n");
+ printf("\t -n: inhibit auto-login\n");
+ printf("\t -e: disable readline support, if present\n");
+ printf("\t -g: disable filename globbing\n");
+ printf("\t -m: don't force data channel interface to the same as control channel\n");
+ printf("\t -v: verbose mode\n");
+ printf("\t -t: enable packet tracing [nonfunctional]\n");
+ printf("\t -d: enable debugging\n");
+ printf("\n");
+}
+
+int
+main(volatile int argc, char **volatile argv)
+{
+ register char *cp;
+ struct servent *sp;
+ int top;
+ struct passwd *pw = NULL;
+ char homedir[MAXPATHLEN];
+
+ tick = 0;
+
+ setlocale (LC_ALL, "");
+ sp = getservbyname("ftp", "tcp");
+ if (sp == 0) {
+ fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
+ exit(1);
+ }
+ ftp_port = sp->s_port;
+ doglob = 1;
+ interactive = 1;
+ autologin = 1;
+ multihome = 1;
+ passivemode = 1;
+
+ cp = strrchr(argv[0], '/');
+ cp = (cp == NULL) ? argv[0] : cp+1;
+ 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++)
+ switch (*cp) {
+
+ case 'd':
+ options |= SO_DEBUG;
+ debug++;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 't':
+ traceflag++;
+ break;
+
+ case 'i':
+ interactive = 0;
+ break;
+
+ case 'n':
+ autologin = 0;
+ break;
+
+ case 'p':
+ passivemode = 1;
+ break;
+
+ case 'A':
+ passivemode = 0;
+ break;
+
+ case 'g':
+ doglob = 0;
+ break;
+
+ case 'e':
+ rl_inhibit = 1;
+ break;
+
+ case 'm':
+ multihome = 0;
+ break;
+
+ case 'h':
+ usage();
+ exit(0);
+
+ default:
+ fprintf(stdout,
+ "ftp: %c: unknown option\n", *cp);
+ exit(1);
+ }
+ argc--, argv++;
+ }
+ fromatty = isatty(fileno(stdin));
+ 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 */
+ /*
+ * Set up the home directory in case we're globbing.
+ */
+ pw = getpwuid(getuid());
+ if (pw != NULL) {
+ strncpy(homedir, pw->pw_dir, sizeof(homedir));
+ homedir[sizeof(homedir)-1] = 0;
+ home = homedir;
+ }
+ if (argc > 0) {
+ if (sigsetjmp(toplevel, 1))
+ exit(0);
+ (void) signal(SIGINT, intr);
+ (void) signal(SIGPIPE, lostpeer);
+ setpeer(argc + 1, argv - 1);
+ }
+ top = sigsetjmp(toplevel, 1) == 0;
+ if (top) {
+ (void) signal(SIGINT, intr);
+ (void) signal(SIGPIPE, lostpeer);
+ }
+ for (;;) {
+ cmdscanner(top);
+ top = 1;
+ }
+}
+
+void
+intr(int ignore)
+{
+ (void)ignore;
+ siglongjmp(toplevel, 1);
+}
+
+void
+lostpeer(int ignore)
+{
+ (void)ignore;
+
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), 1+1);
+ }
+ if (data >= 0) {
+ shutdown(data, 1+1);
+ close(data);
+ data = -1;
+ }
+ connected = 0;
+ }
+ pswitch(1);
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), 1+1);
+ }
+ connected = 0;
+ }
+ proxflag = 0;
+ pswitch(0);
+}
+
+/*char *
+tail(filename)
+ char *filename;
+{
+ register char *s;
+
+ while (*filename) {
+ s = rindex(filename, '/');
+ if (s == NULL)
+ break;
+ if (s[1])
+ return (s + 1);
+ *s = '\0';
+ }
+ return (filename);
+}
+*/
+
+static char *get_input_line(char *buf, int buflen)
+{
+#ifdef __USE_READLINE__
+ if (fromatty && !rl_inhibit) {
+ char *lineread = readline("ftp> ");
+ if (!lineread) return NULL;
+ strncpy(buf, lineread, buflen);
+ buf[buflen-1] = 0;
+ if (lineread[0]) add_history(lineread);
+ free(lineread);
+ return buf;
+ }
+#endif
+ if (fromatty) {
+ printf("ftp> ");
+ fflush(stdout);
+ }
+ return fgets(buf, buflen, stdin);
+}
+
+
+/*
+ * Command parser.
+ */
+static void
+cmdscanner(int top)
+{
+ int margc;
+ char *marg;
+ char **margv;
+ register struct cmd *c;
+ register int l;
+
+ if (!top)
+ (void) putchar('\n');
+ for (;;) {
+ if (!get_input_line(line, sizeof(line))) {
+ quit();
+ }
+ l = strlen(line);
+ if (l == 0)
+ break;
+ if (line[--l] == '\n') {
+ if (l == 0)
+ 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;
+ }
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == NULL) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->c_conn && !connected) {
+ printf("Not connected.\n");
+ continue;
+ }
+ if (c->c_handler_v) c->c_handler_v(margc, margv);
+ else if (c->c_handler_0) c->c_handler_0();
+ else c->c_handler_1(marg);
+
+ if (bell && c->c_bell) putchar('\007');
+ if (c->c_handler_v != help)
+ break;
+ }
+ (void) signal(SIGINT, intr);
+ (void) signal(SIGPIPE, lostpeer);
+}
+
+struct cmd *
+getcmd(const char *name)
+{
+ const char *p, *q;
+ struct cmd *c, *found;
+ int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; (p = c->c_name) != NULL; c++) {
+ for (q = name; *q == *p++; q++)
+ if (*q == 0) /* exact match? */
+ return (c);
+ if (!*q) { /* the name was a prefix */
+ if (q - name > longest) {
+ longest = q - name;
+ nmatches = 1;
+ found = c;
+ } else if (q - name == longest)
+ nmatches++;
+ }
+ }
+ if (nmatches > 1)
+ return ((struct cmd *)-1);
+ return (found);
+}
+
+/*
+ * Slice a string up into argc/argv.
+ */
+
+int slrflag;
+
+char **
+makeargv(int *pargc, char **parg)
+{
+ static char *rargv[20];
+ int rargc = 0;
+ char **argp;
+
+ argp = rargv;
+ stringbase = line; /* scan from first of buffer */
+ argbase = argbuf; /* store from first of buffer */
+ slrflag = 0;
+ while ((*argp++ = slurpstring())!=NULL)
+ rargc++;
+
+ *pargc = rargc;
+ if (parg) *parg = altarg;
+ return rargv;
+}
+
+/*
+ * Parse string into argbuf;
+ * implemented with FSM to
+ * handle quoting and strings
+ */
+static
+char *
+slurpstring(void)
+{
+ static char excl[] = "!", dols[] = "$";
+
+ int got_one = 0;
+ register char *sb = stringbase;
+ register char *ap = argbase;
+ char *tmp = argbase; /* will return this if token found */
+
+ if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
+ switch (slrflag) { /* and $ as token for macro invoke */
+ case 0:
+ slrflag++;
+ stringbase++;
+ return ((*sb == '!') ? excl : dols);
+ /* NOTREACHED */
+ case 1:
+ slrflag++;
+ altarg = stringbase;
+ break;
+ default:
+ break;
+ }
+ }
+
+S0:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ case ' ':
+ case '\t':
+ sb++; goto S0;
+
+ default:
+ switch (slrflag) {
+ case 0:
+ slrflag++;
+ break;
+ case 1:
+ slrflag++;
+ altarg = sb;
+ break;
+ default:
+ break;
+ }
+ goto S1;
+ }
+
+S1:
+ switch (*sb) {
+
+ case ' ':
+ case '\t':
+ case '\0':
+ goto OUT; /* end of token */
+
+ case '\\':
+ sb++; goto S2; /* slurp next character */
+
+ case '"':
+ sb++; goto S3; /* slurp quoted string */
+
+ default:
+ *ap++ = *sb++; /* add character to token */
+ got_one = 1;
+ goto S1;
+ }
+
+S2:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ default:
+ *ap++ = *sb++;
+ got_one = 1;
+ goto S1;
+ }
+
+S3:
+ switch (*sb) {
+
+ case '\0':
+ goto OUT;
+
+ case '"':
+ sb++; goto S1;
+
+ default:
+ *ap++ = *sb++;
+ got_one = 1;
+ goto S3;
+ }
+
+OUT:
+ if (got_one)
+ *ap++ = '\0';
+ argbase = ap; /* update storage pointer */
+ stringbase = sb; /* update scan pointer */
+ if (got_one) {
+ return(tmp);
+ }
+ switch (slrflag) {
+ case 0:
+ slrflag++;
+ break;
+ case 1:
+ slrflag++;
+ altarg = NULL;
+ break;
+ default:
+ break;
+ }
+ return NULL;
+}
+
+#define HELPINDENT ((int) sizeof ("directory"))
+
+/*
+ * Help command.
+ * Call each command handler with argc == 0 and argv[0] == name.
+ */
+void
+help(int argc, char *argv[])
+{
+ struct cmd *c;
+
+ if (argc == 1) {
+ int i, j, w;
+ unsigned k;
+ int columns, width = 0, lines;
+
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
+ int len = strlen(c->c_name);
+
+ if (len > width)
+ width = len;
+ }
+ width = (width + 8) &~ 7;
+ columns = 80 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ for (j = 0; j < columns; j++) {
+ c = cmdtab + j * lines + i;
+ if (c->c_name && (!proxy || c->c_proxy)) {
+ printf("%s", c->c_name);
+ }
+ else if (c->c_name) {
+ for (k=0; k < strlen(c->c_name); k++) {
+ (void) putchar(' ');
+ }
+ }
+ if (c + lines >= &cmdtab[NCMDS]) {
+ printf("\n");
+ break;
+ }
+ w = strlen(c->c_name);
+ while (w < width) {
+ w = (w + 8) &~ 7;
+ (void) putchar('\t');
+ }
+ }
+ }
+ return;
+ }
+ while (--argc > 0) {
+ register char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == NULL)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%-*s\t%s\n", HELPINDENT,
+ c->c_name, c->c_help);
+ }
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp/ruserpass.c
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp/ruserpass.c (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp/ruserpass.c (revision 5)
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ */
+
+/*
+ * from: @(#)ruserpass.c 5.3 (Berkeley) 3/1/91
+ */
+char ruserpass_rcsid[] =
+ "$Id: ruserpass.c,v 1.9 1999/10/02 19:12:33 dholland Exp $";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <utmp.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include "ftp_var.h"
+
+static FILE *cfile;
+static int token(void);
+
+#define DEFAULT 1
+#define LOGIN 2
+#define PASSWD 3
+#define ACCOUNT 4
+#define MACDEF 5
+#define ID 10
+#define MACH 11
+
+#define MAXTOKENLEN 4096
+static char tokval[MAXTOKENLEN];
+
+static struct toktab {
+ const char *tokstr;
+ int tval;
+} toktab[]= {
+ { "default", DEFAULT },
+ { "login", LOGIN },
+ { "password", PASSWD },
+ { "passwd", PASSWD },
+ { "account", ACCOUNT },
+ { "machine", MACH },
+ { "macdef", MACDEF },
+ { NULL, 0 }
+};
+
+int
+xruserpass(const char *host, char **aname, char **apass, char **aacct)
+{
+ const char *hdir;
+ char buf[BUFSIZ], *tmp;
+ char myname[MAXHOSTNAMELEN];
+ const char *mydomain;
+ int t, i, c, usedefault = 0;
+ struct stat stb;
+
+ hdir = getenv("HOME");
+ if (hdir == NULL)
+ hdir = ".";
+ snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
+ cfile = fopen(buf, "r");
+ if (cfile == NULL) {
+ if (errno != ENOENT)
+ perror(buf);
+ return(0);
+ }
+ if (gethostname(myname, sizeof(myname)) < 0)
+ myname[0] = '\0';
+ if ((mydomain = strchr(myname, '.')) == NULL)
+ mydomain = "";
+next:
+ while ((t = token())) switch(t) {
+
+ case DEFAULT:
+ usedefault = 1;
+ /* FALL THROUGH */
+
+ case MACH:
+ if (!usedefault) {
+ if (token() != ID)
+ continue;
+ /*
+ * Allow match either for user's input host name
+ * or official hostname. Also allow match of
+ * incompletely-specified host in local domain.
+ */
+ if (strcasecmp(host, tokval) == 0)
+ goto match;
+ if (strcasecmp(hostname, tokval) == 0)
+ goto match;
+ if ((tmp = index(hostname, '.')) != NULL &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
+ tokval[tmp - hostname] == '\0')
+ goto match;
+ if ((tmp = index(host, '.')) != NULL &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(host, tokval, tmp - host) == 0 &&
+ tokval[tmp - host] == '\0')
+ goto match;
+ continue;
+ }
+ match:
+ while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
+
+ case LOGIN:
+ if (token()) {
+ if (*aname == 0) {
+ *aname = malloc((unsigned) strlen(tokval) + 1);
+ if (*aname != NULL)
+ (void) strcpy(*aname, tokval);
+ } else {
+ if (strcmp(*aname, tokval))
+ goto next;
+ }
+ }
+ break;
+ case PASSWD:
+ if (*aname==NULL) {
+ fprintf(stderr, "Error: `password' must follow `login' in .netrc\n");
+ goto bad;
+ }
+ if (strcmp(*aname, "anonymous") &&
+ fstat(fileno(cfile), &stb) >= 0 &&
+ (stb.st_mode & 077) != 0) {
+ fprintf(stderr, "Error - .netrc file not correct permissions.\n");
+ fprintf(stderr, "Remove password or correct mode (should be 600).\n");
+ goto bad;
+ }
+ if (token() && *apass == 0) {
+ *apass = malloc((unsigned) strlen(tokval) + 1);
+ if (*apass != NULL)
+ (void) strcpy(*apass, tokval);
+ }
+ break;
+ case ACCOUNT:
+ if (fstat(fileno(cfile), &stb) >= 0
+ && (stb.st_mode & 077) != 0) {
+ fprintf(stderr, "Error - .netrc file not correct permissions.\n");
+ fprintf(stderr, "Remove account or correct mode (should be 600).\n");
+ goto bad;
+ }
+ if (token() && *aacct == 0) {
+ *aacct = malloc((unsigned) strlen(tokval) + 1);
+ if (*aacct != NULL)
+ (void) strcpy(*aacct, tokval);
+ }
+ break;
+ case MACDEF:
+ if (proxy) {
+ (void) fclose(cfile);
+ return(0);
+ }
+ while ((c=getc(cfile)) != EOF && (c == ' ' || c == '\t'));
+ if (c == EOF || c == '\n') {
+ printf("Missing macdef name argument.\n");
+ goto bad;
+ }
+ if (macnum == 16) {
+ printf("Limit of 16 macros have already been defined\n");
+ goto bad;
+ }
+ tmp = macros[macnum].mac_name;
+ *tmp++ = c;
+ for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
+ !isspace(c); ++i) {
+ *tmp++ = c;
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = '\0';
+ if (c != '\n') {
+ while ((c=getc(cfile)) != EOF && c != '\n');
+ }
+ if (c == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ if (macnum == 0) {
+ macros[macnum].mac_start = macbuf;
+ }
+ else {
+ macros[macnum].mac_start = macros[macnum-1].mac_end + 1;
+ }
+ tmp = macros[macnum].mac_start;
+ while (tmp != macbuf + MACBUF_SIZE) {
+ if ((c=getc(cfile)) == EOF) {
+ printf("Macro definition missing null line terminator.\n");
+ goto bad;
+ }
+ *tmp = c;
+ if (*tmp == '\n') {
+ if (*(tmp-1) == '\0') {
+ macros[macnum++].mac_end = tmp - 1;
+ break;
+ }
+ *tmp = '\0';
+ }
+ tmp++;
+ }
+ if (tmp == macbuf + MACBUF_SIZE) {
+ printf("4K macro buffer exceeded\n");
+ goto bad;
+ }
+ break;
+ default:
+ fprintf(stderr, "Unknown .netrc keyword %s\n", tokval);
+ break;
+ }
+ goto done;
+ }
+done:
+ (void) fclose(cfile);
+ return(0);
+bad:
+ (void) fclose(cfile);
+ return(-1);
+}
+
+static
+int
+token(void)
+{
+ char *cp;
+ int c;
+ struct toktab *t;
+ size_t toklen = 0;
+ int showwarn = 1;
+ int quote = 0;
+
+ if (feof(cfile))
+ return (0);
+ while ((c = getc(cfile)) != EOF &&
+ (c == '\n' || c == '\t' || c == ' ' || c == ','))
+ continue;
+ if (c == EOF)
+ return (0);
+ cp = tokval;
+ if (c == '"') {
+ quote = 1;
+ }
+ else {
+ *cp++ = c;
+ toklen++;
+ }
+ while ((c = getc(cfile)) != EOF) {
+ if (c == '"') {
+ break;
+ }
+ if (c == '\\') {
+ c = getc(cfile);
+ }
+ if (!quote && (c == '\n' || c == '\t' || c == ' ' || c == ',')) {
+ break;
+ }
+ if (toklen >= MAXTOKENLEN) {
+ if (showwarn) {
+ fprintf(stderr,
+ "Warning: .netrc token too long, will be trunctated to %zd characters\n",
+ toklen);
+ showwarn = 0;
+ }
+ continue;
+ }
+ *cp++ = c;
+ toklen++;
+ }
+
+ *cp = 0;
+ if (tokval[0] == 0)
+ return (0);
+ for (t = toktab; t->tokstr; t++)
+ if (!strcmp(t->tokstr, tokval))
+ return (t->tval);
+ return (ID);
+}
Index: create-0.17-patch/netkit-ftp-0.17-new/ftp
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new/ftp (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new/ftp (revision 5)
Property changes on: create-0.17-patch/netkit-ftp-0.17-new/ftp
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: create-0.17-patch/netkit-ftp-0.17-new
===================================================================
--- create-0.17-patch/netkit-ftp-0.17-new (nonexistent)
+++ create-0.17-patch/netkit-ftp-0.17-new (revision 5)
Property changes on: create-0.17-patch/netkit-ftp-0.17-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: create-0.17-patch
===================================================================
--- create-0.17-patch (nonexistent)
+++ create-0.17-patch (revision 5)
Property changes on: create-0.17-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: patches/README
===================================================================
--- patches/README (nonexistent)
+++ patches/README (revision 5)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+ TODO: Leave some comment here.
+
+ * end */
Index: patches
===================================================================
--- patches (nonexistent)
+++ patches (revision 5)
Property changes on: patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 5)
Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~