summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/appl/ftp
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/appl/ftp')
-rw-r--r--crypto/heimdal/appl/ftp/ChangeLog414
-rw-r--r--crypto/heimdal/appl/ftp/Makefile.am5
-rw-r--r--crypto/heimdal/appl/ftp/Makefile.in598
-rw-r--r--crypto/heimdal/appl/ftp/common/Makefile.am12
-rw-r--r--crypto/heimdal/appl/ftp/common/Makefile.in611
-rw-r--r--crypto/heimdal/appl/ftp/common/buffer.c69
-rw-r--r--crypto/heimdal/appl/ftp/common/common.h60
-rw-r--r--crypto/heimdal/appl/ftp/common/sockbuf.c56
-rw-r--r--crypto/heimdal/appl/ftp/ftp/Makefile.am46
-rw-r--r--crypto/heimdal/appl/ftp/ftp/Makefile.in702
-rw-r--r--crypto/heimdal/appl/ftp/ftp/cmds.c2116
-rw-r--r--crypto/heimdal/appl/ftp/ftp/cmdtab.c202
-rw-r--r--crypto/heimdal/appl/ftp/ftp/domacro.c138
-rw-r--r--crypto/heimdal/appl/ftp/ftp/extern.h173
-rw-r--r--crypto/heimdal/appl/ftp/ftp/ftp.11193
-rw-r--r--crypto/heimdal/appl/ftp/ftp/ftp.c1746
-rw-r--r--crypto/heimdal/appl/ftp/ftp/ftp_locl.h139
-rw-r--r--crypto/heimdal/appl/ftp/ftp/ftp_var.h127
-rw-r--r--crypto/heimdal/appl/ftp/ftp/globals.c76
-rw-r--r--crypto/heimdal/appl/ftp/ftp/gssapi.c379
-rw-r--r--crypto/heimdal/appl/ftp/ftp/kauth.c198
-rw-r--r--crypto/heimdal/appl/ftp/ftp/krb4.c334
-rw-r--r--crypto/heimdal/appl/ftp/ftp/main.c549
-rw-r--r--crypto/heimdal/appl/ftp/ftp/pathnames.h44
-rw-r--r--crypto/heimdal/appl/ftp/ftp/ruserpass.c313
-rw-r--r--crypto/heimdal/appl/ftp/ftp/security.c785
-rw-r--r--crypto/heimdal/appl/ftp/ftp/security.h131
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/Makefile.am56
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/Makefile.in768
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/extern.h160
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ftpcmd.y1455
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ftpd.8473
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ftpd.c2249
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h170
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ftpusers.538
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/gss_userok.c69
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/kauth.c365
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/logwtmp.c137
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/ls.c588
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/pathnames.h58
-rw-r--r--crypto/heimdal/appl/ftp/ftpd/popen.c224
41 files changed, 18026 insertions, 0 deletions
diff --git a/crypto/heimdal/appl/ftp/ChangeLog b/crypto/heimdal/appl/ftp/ChangeLog
new file mode 100644
index 0000000..1a55c38
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ChangeLog
@@ -0,0 +1,414 @@
+2000-01-08 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c (hookup): handle ai_canonname being set in any of the
+ addresses returnedby getaddrinfo. glibc apparently returns the
+ reverse lookup of every address in ai_canonname.
+ * ftp/ruserpass.c (guess_domain): dito
+
+1999-12-21 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c: don't use sa_len as a parameter, it's defined on
+ Irix
+
+1999-12-21 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c (dataconn): make sure from points to actual data
+
+1999-12-16 Assar Westerlund <assar@sics.se>
+
+ * ftp/ruserpass.c (guess_domain): handle ai_canonname not being
+ set
+ * ftp/ftp.c (hookup): handle ai_canonname not being set
+
+1999-12-06 Assar Westerlund <assar@sics.se>
+
+ * ftp/krb4.c (krb4_auth): the nat-IP address might not be realm
+ bounded.
+
+1999-12-05 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (dolog): update prototype
+ * ftpd/ftpd.c (dolog): use getnameinfo_verified
+ * ftpd/ftpd.c: replace inaddr2str by getnameinfo
+
+1999-12-04 Assar Westerlund <assar@sics.se>
+
+ * ftp/ruserpass.c (guess_domain): re-write to use getaddrinfo
+ * ftp/ftp.c (hookup): re-write to use getaddrinfo
+
+1999-11-30 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (getdatasock): make sure to keep the port-number of
+ the outgoing connections. It has to be `ftp-data' or some people
+ might get upset.
+
+ * ftpd/ftpd.c (args): set correct variable when `-l' so that
+ logging actually works
+
+1999-11-29 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c (sec_login): check return value from realloc
+ (sec_end): set app_data to NULL
+
+1999-11-25 Assar Westerlund <assar@sics.se>
+
+ * ftp/krb4.c (krb4_auth): obtain the `local' address when doing
+ NAT. also turn on passive mode. From <thn@stacken.kth.se>
+
+1999-11-20 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (make_fileinfo): cast to allow for non-const
+ prototypes of readlink
+
+1999-11-12 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (args): use arg_counter for `l'
+
+1999-11-04 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (S_ISSOCK, S_ISLNK): fallback definitions for systems
+ that don't have them (such as ultrix)
+
+1999-10-29 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (make_fileinfo): cast uid's and gid's to unsigned in
+ printf, we don't know what types they might be.
+ (lstat_file): conditionalize the kafs part on KRB4
+
+ * ftpd/ftpd_locl.h: <sys/ioccom.h> is needed for kafs.h
+
+1999-10-28 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c (lstat_file): don't set st_mode, it should already be
+ correct
+
+ * ftpd/ls.c: don't use warnx to print errors
+
+ * ftpd/ls.c (builtin_ls): fix typo, 'd' shouldn't imply 'f'
+
+ * ftpd/ls.c (lstat_file): new function for avoiding stating AFS
+ mount points. From Love <lha@s3.kth.se>
+ (list_files): use `lstat_file'
+
+ * ftpd/ftpd.c: some const-poisoning
+
+ * ftpd/ftpd.c (args): add `-B' as an alias for `--builtin-ls' to
+ allow for stupid inetds that only support two arguments. From
+ Love <lha@s3.kth.se>
+
+1999-10-26 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y (help): it's unnecessary to interpret help strings
+ as printf commands
+
+ * ftpd/ftpd.c (show_issue): don't interpret contents of
+ /etc/issue* as printf commands. From Brian A May
+ <bmay@dgs.monash.edu.au>
+
+1999-10-21 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/kauth.c (kauth): complain if protection level isn't
+ `private'
+
+ * ftp/krb4.c (krb4_decode): syslog failure reason
+
+ * ftp/kauth.c (kauth): set private level earlier
+
+ * ftp/security.c: get_command_prot; (sec_prot): partially match
+ `command' and `data'
+
+1999-10-18 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c: change `-l' flag to use arg_collect (this makes
+ `-ll' work again)
+
+ * ftpd/ftpd.c (list_file): pass filename to ls
+
+1999-10-04 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpcmd.y: FEAT
+
+1999-10-03 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ls.c: fall-back definitions for constans and casts for
+ printfs
+
+1999-10-03 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c (main): make this use getarg; add `list_file'
+
+ * ftpd/ftpcmd.y (LIST): call list_file
+
+ * ftpd/ls.c: add simple built-in ls
+
+ * ftp/security.c: add `sec_vfprintf2' and `sec_fprintf2' that
+ prints to the data stream
+
+ * ftp/kauth.c (kauth): make sure we're using private protection
+ level
+
+ * ftp/security.c (set_command_prot): set command protection level
+
+ * ftp/security.c: make it possible to set the command protection
+ level with `prot'
+
+1999-09-30 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd_locl.h: add prototype for fclose to make sunos happy
+
+1999-08-19 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpd.c (do_login): show issue-file
+ (send_data): change handling of zero-byte files
+
+1999-08-18 Assar Westerlund <assar@sics.se>
+
+ * ftp/cmds.c (getit): be more suspicious when parsing the result
+ of MDTM. Do the comparison of timestamps correctly.
+
+1999-08-13 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (send_data): avoid calling mmap with `len == 0'.
+ Some mmap:s rather dislike that (Solaris) and some munmap (Linux)
+ get grumpy later.
+
+ * ftp/ftp.c (copy_stream): avoid calling mmap with `len == 0'.
+ Some mmap:s rather dislike that (Solaris) and some munmap (Linux)
+ get grumpy later.
+
+1999-08-03 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c (active_mode): hide failure of EPRT by setting verbose
+
+ * ftp/gssapi.c (gss_auth): initialize application_data in bindings
+
+1999-08-02 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: save file names when doing commands that might
+ get aborted (and longjmp:ed out of) to avoid overwriting them also
+ remove extra closing brace
+
+1999-08-01 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftpd/ftpcmd.y: change `site find' to `site locate' (to match
+ what it does, and other implementations) keep find as an alias
+
+1999-07-28 Assar Westerlund <assar@sics.se>
+
+ * common/socket.c: moved to roken
+
+ * common/socket.c: new file with generic socket functions
+
+ * ftpd/ftpd.c: make it more AF-neutral and v6-capable
+
+ * ftpd/ftpcmd.y: add EPRT and EPSV
+
+ * ftpd/extern.h: update prototypes and variables
+
+ * ftp/krb4.c: update to new types of addresses
+
+ * ftp/gssapi.c: add support for both AF_INET and AF_INET6
+ addresses
+
+ * ftp/ftp.c: make it more AF-neutral and v6-capable
+
+ * ftp/extern.h (hookup): change prototype
+
+ * common/common.h: add prototypes for functions in socket.c
+
+ * common/Makefile.am (libcommon_a_SOURCES): add socket.c
+
+ * ftp/gssapi.c (gss_auth): check return value from
+ `gss_import_name' and print error messages if it fails
+
+1999-06-15 Assar Westerlund <assar@sics.se>
+
+ * ftp/krb4.c (krb4_auth): type correctness
+
+1999-06-02 Johan Danielsson <joda@pdc.kth.se>
+
+ * ftp/ftp.c (sendrequest): lmode != rmode
+
+1999-05-21 Assar Westerlund <assar@sics.se>
+
+ * ftp/extern.h (sendrequest): update prototype
+
+ * ftp/cmds.c: update calls to sendrequest and recvrequest to send
+ "b" when appropriate
+
+ * ftp/ftp.c (sendrequest): add argument for mode to open file in.
+
+1999-05-08 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: rename getline -> ftpd_getline
+
+ * ftp/main.c (makeargv): fill in unused slots with NULL
+
+Thu Apr 8 15:06:40 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd.c: remove definition of KRB_VERIFY_USER (moved to
+ config.h)
+
+Wed Apr 7 16:15:21 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftp/gssapi.c (gss_auth): call gss_display_status to get a sane
+ error message; return AUTH_{CONTINUE,ERROR}, where appropriate
+
+ * ftp/krb4.c: return AUTH_{CONTINUE,ERROR}, where appropriate
+
+ * ftp/security.c (sec_login): if mechanism returns AUTH_CONTINUE,
+ just continue with the next mechanism, this fixes the case of
+ having GSSAPI fail because of non-existant of expired tickets
+
+ * ftp/security.h: add AUTH_{OK,CONTINUE,ERROR}
+
+Thu Apr 1 16:59:04 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: don't run check-local
+
+ * ftp/Makefile.am: don't run check-local
+
+Mon Mar 22 22:15:18 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (pass): fall-back for KRB_VERIFY_SECURE
+
+ * ftpd/ftpd.c (pass): 1 -> KRB_VERIFY_SECURE
+
+Thu Mar 18 12:07:09 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: clean ftpcmd.c
+
+ * ftpd/ftpd_locl.h: remove krb5.h (breaks in ftpcmd.y)
+
+ * ftpd/ftpd.c: move include of krb5.h here
+
+ * ftpd/Makefile.am: include Makefile.am.common
+
+ * Makefile.am: include Makefile.am.common
+
+ * ftp/Makefile.am: include Makefile.am.common
+
+ * common/Makefile.am: include Makefile.am.common
+
+Tue Mar 16 22:28:37 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd_locl.h: add krb5.h to get heimdal_version
+
+ * ftpd/ftpd.c: krb_verify_user_multiple -> krb_verify_user
+
+Thu Mar 11 14:54:59 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftp/Makefile.in: WFLAGS
+
+ * ftp/ruserpass.c: add some if-braces
+
+Wed Mar 10 20:02:55 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd_locl.h: remove ifdef HAVE_FNMATCH
+
+Mon Mar 8 21:29:24 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/ftpd.c: re-add version in greeting message
+
+Mon Mar 1 10:49:38 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/logwtmp.c: HAVE_UT_* -> HAVE_STRUCT_UTMP*_UT_*
+
+Mon Feb 22 19:20:51 1999 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * common/Makefile.in: remove glob
+
+Sat Feb 13 17:19:35 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (match): remove #ifdef HAVE_FNMATCH. We have a
+ fnmatch implementation in roken and therefore always have it.
+
+ * ftp/ftp.c (copy_stream): initialize `werr'
+
+Wed Jan 13 23:52:57 1999 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpcmd.y: moved all check_login and check_login_no_guest to
+ the end of the rules to ensure we don't generate several
+ (independent) error messages. once again, having a yacc-grammar
+ for FTP with embedded actions doesn't strike me as the most
+ optimal way of doing it.
+
+Tue Dec 1 14:44:29 1998 Johan Danielsson <joda@hella.pdc.kth.se>
+
+ * ftpd/Makefile.am: link with extra libs for aix
+
+Sun Nov 22 10:28:20 1998 Assar Westerlund <assar@sics.se>
+
+ * ftpd/ftpd.c (retrying): support on-the-fly decompression
+
+ * ftpd/Makefile.in (WFLAGS): set
+
+ * ftp/ruserpass.c (guess_domain): new function
+ (ruserpass): use it
+
+ * common/Makefile.in (WFLAGS): set
+
+ * Makefile.in (WFLAGS): set
+
+Sat Nov 21 23:13:03 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c: some more type correctness.
+
+ * ftp/gssapi.c (gss_adat): more braces to shut up warnings
+
+Wed Nov 18 21:47:55 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/main.c (main): new option `-p' for enable passive mode.
+
+Mon Nov 2 01:57:49 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c (getreply): remove extra `break'
+
+ * ftp/gssapi.c (gss_auth): fixo typo(copyo?)
+
+ * ftp/security.c (sec_login): fix loop and return value
+
+Tue Sep 1 16:56:42 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/cmds.c (quote1): fix % quoting bug
+
+Fri Aug 14 17:10:06 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/krb4.c: krb_put_int -> KRB_PUT_INT
+
+Tue Jun 30 18:07:15 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/security.c (auth): free `app_data'
+ (sec_end): only destroy if it was initialized
+
+Tue Jun 9 21:01:59 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/krb4.c: pass client address to krb_rd_req
+
+Sat May 16 00:02:07 1998 Assar Westerlund <assar@sics.se>
+
+ * ftpd/Makefile.am: link with DBLIB
+
+Tue May 12 14:15:32 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/gssapi.c: Save client name for userok().
+
+ * ftpd/gss_userok.c: Userok for gssapi.
+
+Fri May 1 07:15:01 1998 Assar Westerlund <assar@sics.se>
+
+ * ftp/ftp.c: unifdef -DHAVE_H_ERRNO
+
+Fri Mar 27 00:46:07 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * Make compile w/o krb4.
+
+Thu Mar 26 03:49:12 1998 Johan Danielsson <joda@emma.pdc.kth.se>
+
+ * ftp/*, ftpd/*: Changes for new framework.
+
+ * ftp/gssapi.c: GSS-API backend for the new security framework.
+
+ * ftp/krb4.c: Updated for new framework.
+
+ * ftp/security.{c,h}: New unified security framework.
diff --git a/crypto/heimdal/appl/ftp/Makefile.am b/crypto/heimdal/appl/ftp/Makefile.am
new file mode 100644
index 0000000..f8831a3
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/Makefile.am
@@ -0,0 +1,5 @@
+# $Id: Makefile.am,v 1.5 1999/03/20 13:58:14 joda Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+SUBDIRS = common ftp ftpd
diff --git a/crypto/heimdal/appl/ftp/Makefile.in b/crypto/heimdal/appl/ftp/Makefile.in
new file mode 100644
index 0000000..9c0d09d
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/Makefile.in
@@ -0,0 +1,598 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id: Makefile.am,v 1.5 1999/03/20 13:58:14 joda Exp $
+
+
+# $Id: Makefile.am.common,v 1.3 1999/04/01 14:58:43 joda Exp $
+
+
+# $Id: Makefile.am.common,v 1.13 1999/11/01 03:19:58 assar Exp $
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AFS_EXTRA_LD = @AFS_EXTRA_LD@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CC = @CC@
+DBLIB = @DBLIB@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+GROFF = @GROFF@
+INCLUDE_ = @INCLUDE_@
+LD = @LD@
+LEX = @LEX@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LIB_ = @LIB_@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_kdb = @LIB_kdb@
+LIB_otp = @LIB_otp@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_X_PROGS_BIN_PROGS = @MAKE_X_PROGS_BIN_PROGS@
+MAKE_X_PROGS_BIN_SCRPTS = @MAKE_X_PROGS_BIN_SCRPTS@
+MAKE_X_PROGS_LIBEXEC_PROGS = @MAKE_X_PROGS_LIBEXEC_PROGS@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NM = @NM@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+YACC = @YACC@
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+SUFFIXES = .et .h .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x
+
+INCLUDES = -I$(top_builddir)/include
+
+AM_CFLAGS = $(WFLAGS)
+
+COMPILE_ET = $(top_builddir)/lib/com_err/compile_et
+
+buildinclude = $(top_builddir)/include
+
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_crypt = @LIB_crypt@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_el_init = @LIB_el_init@
+LIB_getattr = @LIB_getattr@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_readline = @LIB_readline@
+LIB_res_search = @LIB_res_search@
+LIB_setpcred = @LIB_setpcred@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+LIB_hesiod = @LIB_hesiod@
+
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
+
+INCLUDE_readline = @INCLUDE_readline@
+
+LEXLIB = @LEXLIB@
+
+cat1dir = $(mandir)/cat1
+cat3dir = $(mandir)/cat3
+cat5dir = $(mandir)/cat5
+cat8dir = $(mandir)/cat8
+
+MANRX = \(.*\)\.\([0-9]\)
+CATSUFFIX = @CATSUFFIX@
+
+NROFF_MAN = groff -mandoc -Tascii
+
+@KRB4_TRUE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/asn1/libasn1.la
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+
+CHECK_LOCAL = $(PROGRAMS)
+
+SUBDIRS = common ftp ftpd
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../include/config.h
+CONFIG_CLEAN_FILES =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = ChangeLog Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .et .h .x
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign appl/ftp/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+
+@SET_MAKE@
+
+all-recursive install-data-recursive install-exec-recursive \
+installdirs-recursive install-recursive uninstall-recursive \
+check-recursive installcheck-recursive info-recursive dvi-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $(MAKEFLAGS); amf=$$2; \
+ dot_seen=no; \
+ rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
+ rev="$$subdir $$rev"; \
+ test "$$subdir" = "." && dot_seen=yes; \
+ done; \
+ test "$$dot_seen" = "no" && rev=". $$rev"; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = appl/ftp
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ for subdir in $(SUBDIRS); do \
+ if test "$$subdir" = .; then :; else \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ chmod 777 $(distdir)/$$subdir; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-recursive
+dvi-am:
+dvi: dvi-recursive
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-recursive
+installcheck-am:
+installcheck: installcheck-recursive
+install-exec-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec: install-exec-recursive
+
+install-data-am: install-data-local
+install-data: install-data-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-recursive
+uninstall-am:
+uninstall: uninstall-recursive
+all-am: Makefile all-local
+all-redirect: all-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs: installdirs-recursive
+installdirs-am:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-recursive
+
+clean-am: clean-tags clean-generic mostlyclean-am
+
+clean: clean-recursive
+
+distclean-am: distclean-tags distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-recursive
+
+maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-recursive
+
+.PHONY: install-data-recursive uninstall-data-recursive \
+install-exec-recursive uninstall-exec-recursive installdirs-recursive \
+uninstalldirs-recursive all-recursive check-recursive \
+installcheck-recursive info-recursive dvi-recursive \
+mostlyclean-recursive distclean-recursive clean-recursive \
+maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check-local check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-local install-data-am \
+install-data install-am install uninstall-am uninstall all-local \
+all-redirect all-am all installdirs-am installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ chmod 0 $$x; fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+ @foo='$(include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " cp $$file $(buildinclude)/$$f"; \
+ cp $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat1-mans:
+ @ext=1;\
+ foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat1dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat1/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat3-mans:
+ @ext=3;\
+ foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat3dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat3/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat5-mans:
+ @ext=5;\
+ foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat5dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat5/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat8-mans:
+ @ext=8;\
+ foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat8dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat8/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat-mans: install-cat1-mans install-cat3-mans install-cat5-mans install-cat8-mans
+
+install-data-local: install-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+
+check-local::
+ @foo='$(CHECK_LOCAL)'; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/crypto/heimdal/appl/ftp/common/Makefile.am b/crypto/heimdal/appl/ftp/common/Makefile.am
new file mode 100644
index 0000000..4fab07b
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/common/Makefile.am
@@ -0,0 +1,12 @@
+# $Id: Makefile.am,v 1.9 1999/07/28 21:15:06 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += $(INCLUDE_krb4)
+
+noinst_LIBRARIES = libcommon.a
+
+libcommon_a_SOURCES = \
+ sockbuf.c \
+ buffer.c \
+ common.h
diff --git a/crypto/heimdal/appl/ftp/common/Makefile.in b/crypto/heimdal/appl/ftp/common/Makefile.in
new file mode 100644
index 0000000..1dc613c
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/common/Makefile.in
@@ -0,0 +1,611 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id: Makefile.am,v 1.9 1999/07/28 21:15:06 assar Exp $
+
+
+# $Id: Makefile.am.common,v 1.3 1999/04/01 14:58:43 joda Exp $
+
+
+# $Id: Makefile.am.common,v 1.13 1999/11/01 03:19:58 assar Exp $
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AFS_EXTRA_LD = @AFS_EXTRA_LD@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CC = @CC@
+DBLIB = @DBLIB@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+GROFF = @GROFF@
+INCLUDE_ = @INCLUDE_@
+LD = @LD@
+LEX = @LEX@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LIB_ = @LIB_@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_kdb = @LIB_kdb@
+LIB_otp = @LIB_otp@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_X_PROGS_BIN_PROGS = @MAKE_X_PROGS_BIN_PROGS@
+MAKE_X_PROGS_BIN_SCRPTS = @MAKE_X_PROGS_BIN_SCRPTS@
+MAKE_X_PROGS_LIBEXEC_PROGS = @MAKE_X_PROGS_LIBEXEC_PROGS@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NM = @NM@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+YACC = @YACC@
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+SUFFIXES = .et .h .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x
+
+INCLUDES = -I$(top_builddir)/include $(INCLUDE_krb4)
+
+AM_CFLAGS = $(WFLAGS)
+
+COMPILE_ET = $(top_builddir)/lib/com_err/compile_et
+
+buildinclude = $(top_builddir)/include
+
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_crypt = @LIB_crypt@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_el_init = @LIB_el_init@
+LIB_getattr = @LIB_getattr@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_readline = @LIB_readline@
+LIB_res_search = @LIB_res_search@
+LIB_setpcred = @LIB_setpcred@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+LIB_hesiod = @LIB_hesiod@
+
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
+
+INCLUDE_readline = @INCLUDE_readline@
+
+LEXLIB = @LEXLIB@
+
+cat1dir = $(mandir)/cat1
+cat3dir = $(mandir)/cat3
+cat5dir = $(mandir)/cat5
+cat8dir = $(mandir)/cat8
+
+MANRX = \(.*\)\.\([0-9]\)
+CATSUFFIX = @CATSUFFIX@
+
+NROFF_MAN = groff -mandoc -Tascii
+
+@KRB4_TRUE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/asn1/libasn1.la
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+
+CHECK_LOCAL = $(PROGRAMS)
+
+noinst_LIBRARIES = libcommon.a
+
+libcommon_a_SOURCES = sockbuf.c buffer.c common.h
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../../include/config.h
+CONFIG_CLEAN_FILES =
+LIBRARIES = $(noinst_LIBRARIES)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../../include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+libcommon_a_LIBADD =
+libcommon_a_OBJECTS = sockbuf.$(OBJEXT) buffer.$(OBJEXT)
+AR = ar
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(libcommon_a_SOURCES)
+OBJECTS = $(libcommon_a_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .1 .3 .5 .8 .S .c .cat1 .cat3 .cat5 .cat8 .et .h .lo .o .obj .s .x
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign appl/ftp/common/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-noinstLIBRARIES:
+
+clean-noinstLIBRARIES:
+ -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
+
+distclean-noinstLIBRARIES:
+
+maintainer-clean-noinstLIBRARIES:
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES)
+ -rm -f libcommon.a
+ $(AR) cru libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD)
+ $(RANLIB) libcommon.a
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = appl/ftp/common
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am:
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec: install-exec-am
+
+install-data-am: install-data-local
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am:
+uninstall: uninstall-am
+all-am: Makefile $(LIBRARIES) all-local
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-noinstLIBRARIES clean-compile clean-libtool clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-noinstLIBRARIES distclean-compile \
+ distclean-libtool distclean-tags distclean-generic \
+ clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \
+clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check-local check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-local install-data-am \
+install-data install-am install uninstall-am uninstall all-local \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ chmod 0 $$x; fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+ @foo='$(include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " cp $$file $(buildinclude)/$$f"; \
+ cp $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat1-mans:
+ @ext=1;\
+ foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat1dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat1/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat3-mans:
+ @ext=3;\
+ foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat3dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat3/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat5-mans:
+ @ext=5;\
+ foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat5dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat5/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat8-mans:
+ @ext=8;\
+ foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat8dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat8/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat-mans: install-cat1-mans install-cat3-mans install-cat5-mans install-cat8-mans
+
+install-data-local: install-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+
+check-local::
+ @foo='$(CHECK_LOCAL)'; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/crypto/heimdal/appl/ftp/common/buffer.c b/crypto/heimdal/appl/ftp/common/buffer.c
new file mode 100644
index 0000000..0385d49
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/common/buffer.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "common.h"
+#include <stdio.h>
+#include <err.h>
+#include "roken.h"
+
+RCSID("$Id: buffer.c,v 1.3 1999/12/02 16:58:29 joda Exp $");
+
+/*
+ * Allocate a buffer enough to handle st->st_blksize, if
+ * there is such a field, otherwise BUFSIZ.
+ */
+
+void *
+alloc_buffer (void *oldbuf, size_t *sz, struct stat *st)
+{
+ size_t new_sz;
+
+ new_sz = BUFSIZ;
+#ifdef HAVE_ST_BLKSIZE
+ if (st)
+ new_sz = max(BUFSIZ, st->st_blksize);
+#endif
+ if(new_sz > *sz) {
+ if (oldbuf)
+ free (oldbuf);
+ oldbuf = malloc (new_sz);
+ if (oldbuf == NULL) {
+ warn ("malloc");
+ *sz = 0;
+ return NULL;
+ }
+ *sz = new_sz;
+ }
+ return oldbuf;
+}
+
diff --git a/crypto/heimdal/appl/ftp/common/common.h b/crypto/heimdal/appl/ftp/common/common.h
new file mode 100644
index 0000000..5949b25
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/common/common.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: common.h,v 1.12 1999/12/02 16:58:29 joda Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#include "base64.h"
+
+void set_buffer_size(int, int);
+
+#include <stdlib.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+void *alloc_buffer (void *oldbuf, size_t *sz, struct stat *st);
+
+#endif /* __COMMON_H__ */
diff --git a/crypto/heimdal/appl/ftp/common/sockbuf.c b/crypto/heimdal/appl/ftp/common/sockbuf.c
new file mode 100644
index 0000000..460cc6f
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/common/sockbuf.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "common.h"
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+RCSID("$Id: sockbuf.c,v 1.3 1999/12/02 16:58:29 joda Exp $");
+
+void
+set_buffer_size(int fd, int read)
+{
+#if defined(SO_RCVBUF) && defined(SO_SNDBUF) && defined(HAVE_SETSOCKOPT)
+ size_t size = 4194304;
+ while(size >= 131072 &&
+ setsockopt(fd, SOL_SOCKET, read ? SO_RCVBUF : SO_SNDBUF,
+ (void *)&size, sizeof(size)) < 0)
+ size /= 2;
+#endif
+}
+
+
diff --git a/crypto/heimdal/appl/ftp/ftp/Makefile.am b/crypto/heimdal/appl/ftp/ftp/Makefile.am
new file mode 100644
index 0000000..e24025c
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/Makefile.am
@@ -0,0 +1,46 @@
+# $Id: Makefile.am,v 1.13 2000/01/06 15:11:43 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_krb4)
+
+bin_PROGRAMS = ftp
+
+CHECK_LOCAL =
+
+if KRB4
+krb4_sources = krb4.c kauth.c
+endif
+if KRB5
+krb5_sources = gssapi.c
+endif
+
+ftp_SOURCES = \
+ cmds.c \
+ cmdtab.c \
+ extern.h \
+ ftp.c \
+ ftp_locl.h \
+ ftp_var.h \
+ main.c \
+ pathnames.h \
+ ruserpass.c \
+ domacro.c \
+ globals.c \
+ security.c \
+ security.h \
+ $(krb4_sources) \
+ $(krb5_sources)
+
+EXTRA_ftp_SOURCES = krb4.c kauth.c gssapi.c
+
+man_MANS = ftp.1
+
+LDADD = \
+ ../common/libcommon.a \
+ $(LIB_gssapi) \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken) \
+ $(LIB_readline)
diff --git a/crypto/heimdal/appl/ftp/ftp/Makefile.in b/crypto/heimdal/appl/ftp/ftp/Makefile.in
new file mode 100644
index 0000000..6f8603d
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/Makefile.in
@@ -0,0 +1,702 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id: Makefile.am,v 1.13 2000/01/06 15:11:43 assar Exp $
+
+
+# $Id: Makefile.am.common,v 1.3 1999/04/01 14:58:43 joda Exp $
+
+
+# $Id: Makefile.am.common,v 1.13 1999/11/01 03:19:58 assar Exp $
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AFS_EXTRA_LD = @AFS_EXTRA_LD@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CC = @CC@
+DBLIB = @DBLIB@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+GROFF = @GROFF@
+INCLUDE_ = @INCLUDE_@
+LD = @LD@
+LEX = @LEX@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LIB_ = @LIB_@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_kdb = @LIB_kdb@
+LIB_otp = @LIB_otp@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_X_PROGS_BIN_PROGS = @MAKE_X_PROGS_BIN_PROGS@
+MAKE_X_PROGS_BIN_SCRPTS = @MAKE_X_PROGS_BIN_SCRPTS@
+MAKE_X_PROGS_LIBEXEC_PROGS = @MAKE_X_PROGS_LIBEXEC_PROGS@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NM = @NM@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+YACC = @YACC@
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+SUFFIXES = .et .h .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x
+
+INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../common $(INCLUDE_readline) $(INCLUDE_krb4)
+
+AM_CFLAGS = $(WFLAGS)
+
+COMPILE_ET = $(top_builddir)/lib/com_err/compile_et
+
+buildinclude = $(top_builddir)/include
+
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_crypt = @LIB_crypt@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_el_init = @LIB_el_init@
+LIB_getattr = @LIB_getattr@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_readline = @LIB_readline@
+LIB_res_search = @LIB_res_search@
+LIB_setpcred = @LIB_setpcred@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+LIB_hesiod = @LIB_hesiod@
+
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
+
+INCLUDE_readline = @INCLUDE_readline@
+
+LEXLIB = @LEXLIB@
+
+cat1dir = $(mandir)/cat1
+cat3dir = $(mandir)/cat3
+cat5dir = $(mandir)/cat5
+cat8dir = $(mandir)/cat8
+
+MANRX = \(.*\)\.\([0-9]\)
+CATSUFFIX = @CATSUFFIX@
+
+NROFF_MAN = groff -mandoc -Tascii
+
+@KRB4_TRUE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/asn1/libasn1.la
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+
+CHECK_LOCAL =
+
+bin_PROGRAMS = ftp
+
+@KRB4_TRUE@krb4_sources = krb4.c kauth.c
+@KRB5_TRUE@krb5_sources = gssapi.c
+
+ftp_SOURCES = cmds.c cmdtab.c extern.h ftp.c ftp_locl.h ftp_var.h main.c pathnames.h ruserpass.c domacro.c globals.c security.c security.h $(krb4_sources) $(krb5_sources)
+
+
+EXTRA_ftp_SOURCES = krb4.c kauth.c gssapi.c
+
+man_MANS = ftp.1
+
+LDADD = ../common/libcommon.a $(LIB_gssapi) $(LIB_krb5) $(LIB_krb4) $(top_builddir)/lib/des/libdes.la $(LIB_roken) $(LIB_readline)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../../include/config.h
+CONFIG_CLEAN_FILES =
+bin_PROGRAMS = ftp$(EXEEXT)
+PROGRAMS = $(bin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../../include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+@KRB4_TRUE@@KRB5_FALSE@ftp_OBJECTS = cmds.$(OBJEXT) cmdtab.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@ftp.$(OBJEXT) main.$(OBJEXT) ruserpass.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@domacro.$(OBJEXT) globals.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@security.$(OBJEXT) krb4.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@kauth.$(OBJEXT)
+@KRB4_FALSE@@KRB5_TRUE@ftp_OBJECTS = cmds.$(OBJEXT) cmdtab.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@ftp.$(OBJEXT) main.$(OBJEXT) ruserpass.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@domacro.$(OBJEXT) globals.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@security.$(OBJEXT) gssapi.$(OBJEXT)
+@KRB4_FALSE@@KRB5_FALSE@ftp_OBJECTS = cmds.$(OBJEXT) cmdtab.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_FALSE@ftp.$(OBJEXT) main.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_FALSE@ruserpass.$(OBJEXT) domacro.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_FALSE@globals.$(OBJEXT) security.$(OBJEXT)
+@KRB4_TRUE@@KRB5_TRUE@ftp_OBJECTS = cmds.$(OBJEXT) cmdtab.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@ftp.$(OBJEXT) main.$(OBJEXT) ruserpass.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@domacro.$(OBJEXT) globals.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@security.$(OBJEXT) krb4.$(OBJEXT) kauth.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@gssapi.$(OBJEXT)
+ftp_LDADD = $(LDADD)
+@KRB5_TRUE@ftp_DEPENDENCIES = ../common/libcommon.a \
+@KRB5_TRUE@$(top_builddir)/lib/gssapi/libgssapi.la \
+@KRB5_TRUE@$(top_builddir)/lib/krb5/libkrb5.la \
+@KRB5_TRUE@$(top_builddir)/lib/asn1/libasn1.la \
+@KRB5_TRUE@$(top_builddir)/lib/des/libdes.la
+@KRB5_FALSE@ftp_DEPENDENCIES = ../common/libcommon.a \
+@KRB5_FALSE@$(top_builddir)/lib/des/libdes.la
+ftp_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man1dir = $(mandir)/man1
+MANS = $(man_MANS)
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(ftp_SOURCES) $(EXTRA_ftp_SOURCES)
+OBJECTS = $(ftp_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .1 .3 .5 .8 .S .c .cat1 .cat3 .cat5 .cat8 .et .h .lo .o .obj .s .x
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign appl/ftp/ftp/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-binPROGRAMS:
+
+clean-binPROGRAMS:
+ -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+
+distclean-binPROGRAMS:
+
+maintainer-clean-binPROGRAMS:
+
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(bindir)
+ @list='$(bin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(bin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+ftp$(EXEEXT): $(ftp_OBJECTS) $(ftp_DEPENDENCIES)
+ @rm -f ftp$(EXEEXT)
+ $(LINK) $(ftp_LDFLAGS) $(ftp_OBJECTS) $(ftp_LDADD) $(LIBS)
+
+install-man1:
+ $(mkinstalldirs) $(DESTDIR)$(man1dir)
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man1dir)/$$inst; \
+ done
+
+uninstall-man1:
+ @list='$(man1_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.1*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man1dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man1dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man1
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man1
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = appl/ftp/ftp
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-binPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec: install-exec-am
+
+install-data-am: install-man install-data-local
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-binPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS) all-local
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(mandir)/man1
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-binPROGRAMS mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-binPROGRAMS clean-compile clean-libtool clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-binPROGRAMS distclean-compile distclean-libtool \
+ distclean-tags distclean-generic clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-binPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-binPROGRAMS distclean-binPROGRAMS clean-binPROGRAMS \
+maintainer-clean-binPROGRAMS uninstall-binPROGRAMS install-binPROGRAMS \
+mostlyclean-compile distclean-compile clean-compile \
+maintainer-clean-compile mostlyclean-libtool distclean-libtool \
+clean-libtool maintainer-clean-libtool install-man1 uninstall-man1 \
+install-man uninstall-man tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi \
+check-local check check-am installcheck-am installcheck install-exec-am \
+install-exec install-data-local install-data-am install-data install-am \
+install uninstall-am uninstall all-local all-redirect all-am all \
+installdirs mostlyclean-generic distclean-generic clean-generic \
+maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ chmod 0 $$x; fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+ @foo='$(include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " cp $$file $(buildinclude)/$$f"; \
+ cp $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat1-mans:
+ @ext=1;\
+ foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat1dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat1/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat3-mans:
+ @ext=3;\
+ foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat3dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat3/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat5-mans:
+ @ext=5;\
+ foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat5dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat5/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat8-mans:
+ @ext=8;\
+ foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat8dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat8/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat-mans: install-cat1-mans install-cat3-mans install-cat5-mans install-cat8-mans
+
+install-data-local: install-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+
+check-local::
+ @foo='$(CHECK_LOCAL)'; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/crypto/heimdal/appl/ftp/ftp/cmds.c b/crypto/heimdal/appl/ftp/ftp/cmds.c
new file mode 100644
index 0000000..7698313
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/cmds.c
@@ -0,0 +1,2116 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+/*
+ * FTP User Program -- Command Routines.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: cmds.c,v 1.36 1999/09/16 20:37:28 assar Exp $");
+
+typedef void (*sighand)(int);
+
+jmp_buf jabort;
+char *mname;
+char *home = "/";
+
+/*
+ * `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, char *prompt)
+{
+ int len = strlen(line), ret;
+
+ if (len >= sizeof(line) - 3) {
+ printf("sorry, arguments too long\n");
+ intr(0);
+ }
+ printf("(%s) ", prompt);
+ line[len++] = ' ';
+ if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
+ intr(0);
+ len += strlen(&line[len]);
+ if (len > 0 && line[len - 1] == '\n')
+ line[len - 1] = '\0';
+ makeargv();
+ 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;
+ short port;
+ struct servent *sp;
+
+ if (connected) {
+ printf("Already connected to %s, use close first.\n",
+ hostname);
+ code = -1;
+ return;
+ }
+ if (argc < 2)
+ another(&argc, &argv, "to");
+ if (argc < 2 || argc > 3) {
+ printf("usage: %s host-name [port]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ sp = getservbyname("ftp", "tcp");
+ if (sp == NULL)
+ errx(1, "You bastard. You removed ftp/tcp from services");
+ port = sp->s_port;
+ if (argc > 2) {
+ port = atoi(argv[2]);
+ if (port <= 0) {
+ printf("%s: bad port number-- %s\n", argv[1], argv[2]);
+ printf ("usage: %s host-name [port]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ port = htons(port);
+ }
+ host = hookup(argv[1], port);
+ if (host) {
+ int overbose;
+
+ connected = 1;
+ /*
+ * Set up defaults for FTP.
+ */
+ strlcpy(typename, "ascii", sizeof(typename));
+ type = TYPE_A;
+ curtype = TYPE_A;
+ strlcpy(formname, "non-print", sizeof(formname));
+ form = FORM_N;
+ strlcpy(modename, "stream", sizeof(modename));
+ mode = MODE_S;
+ strlcpy(structname, "file", sizeof(structname));
+ stru = STRU_F;
+ strlcpy(bytename, "8", sizeof(bytename));
+ bytesize = 8;
+ if (autologin)
+ login(argv[1]);
+
+#if (defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY)) && NBBY == 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) {
+ char *cp, c;
+ cp = strchr(reply_string+4, ' ');
+ if (cp == NULL)
+ cp = strchr(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;
+ strlcpy(typename, "binary", sizeof(typename));
+ if (overbose)
+ printf("Using %s mode to transfer files.\n",
+ typename);
+ } else {
+ if (proxy)
+ unix_proxy = 0;
+ else
+ unix_server = 0;
+ if (overbose &&
+ !strncmp(reply_string, "215 TOPS20", 10))
+ printf(
+"Remember to set tenex mode when transfering binary files from this machine.\n");
+ }
+ verbose = overbose;
+#endif /* unix */
+ }
+}
+
+struct types {
+ char *t_name;
+ char *t_mode;
+ int t_type;
+ char *t_arg;
+} types[] = {
+ { "ascii", "A", TYPE_A, 0 },
+ { "binary", "I", TYPE_I, 0 },
+ { "image", "I", TYPE_I, 0 },
+ { "ebcdic", "E", TYPE_E, 0 },
+ { "tenex", "L", TYPE_L, bytename },
+ { NULL }
+};
+
+/*
+ * Set transfer type.
+ */
+void
+settype(int argc, char **argv)
+{
+ struct types *p;
+ int comret;
+
+ if (argc > 2) {
+ 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;
+ }
+ for (p = types; p->t_name; p++)
+ if (strcmp(argv[1], p->t_name) == 0)
+ break;
+ if (p->t_name == 0) {
+ printf("%s: unknown mode\n", argv[1]);
+ 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) {
+ strlcpy(typename, p->t_name, sizeof(typename));
+ curtype = type = p->t_type;
+ }
+}
+
+/*
+ * 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)
+{
+ struct types *p;
+ int comret, oldverbose = verbose;
+
+ if (newtype == 0)
+ newtype = TYPE_I;
+ if (newtype == curtype)
+ return;
+ if (debug == 0 && show == 0)
+ verbose = 0;
+ for (p = types; p->t_name; p++)
+ if (newtype == p->t_type)
+ break;
+ if (p->t_name == 0) {
+ printf("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;
+}
+
+char *stype[] = {
+ "type",
+ "",
+ 0
+};
+
+/*
+ * Set binary transfer type.
+ */
+/*VARARGS*/
+void
+setbinary(int argc, char **argv)
+{
+
+ stype[1] = "binary";
+ settype(2, stype);
+}
+
+/*
+ * Set ascii transfer type.
+ */
+/*VARARGS*/
+void
+setascii(int argc, char **argv)
+{
+
+ stype[1] = "ascii";
+ settype(2, stype);
+}
+
+/*
+ * Set tenex transfer type.
+ */
+/*VARARGS*/
+void
+settenex(int argc, char **argv)
+{
+
+ stype[1] = "tenex";
+ settype(2, stype);
+}
+
+/*
+ * Set file transfer mode.
+ */
+/*ARGSUSED*/
+void
+setftmode(int argc, char **argv)
+{
+
+ printf("We only support %s mode, sorry.\n", modename);
+ code = -1;
+}
+
+/*
+ * Set file transfer format.
+ */
+/*ARGSUSED*/
+void
+setform(int argc, char **argv)
+{
+
+ printf("We only support %s format, sorry.\n", formname);
+ code = -1;
+}
+
+/*
+ * Set file transfer structure.
+ */
+/*ARGSUSED*/
+void
+setstruct(int argc, char **argv)
+{
+
+ printf("We only support %s structure, sorry.\n", structname);
+ code = -1;
+}
+
+/*
+ * Send a single file.
+ */
+void
+put(int argc, char **argv)
+{
+ 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];
+ if (!globulize(&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],
+ curtype == TYPE_I ? "rb" : "r",
+ argv[1] != oldargv1 || argv[2] != oldargv2);
+}
+
+/* ARGSUSED */
+static RETSIGTYPE
+mabort(int signo)
+{
+ int ointer;
+
+ printf("\n");
+ fflush(stdout);
+ if (mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", mname)) {
+ interactive = ointer;
+ longjmp(jabort,0);
+ }
+ interactive = ointer;
+ }
+ mflag = 0;
+ longjmp(jabort,0);
+}
+
+/*
+ * Send multiple files.
+ */
+void
+mput(int argc, char **argv)
+{
+ int i;
+ RETSIGTYPE (*oldintr)();
+ 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);
+ setjmp(jabort);
+ if (proxy) {
+ char *cp, *tp2, tmpbuf[MaxPathLen];
+
+ 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,
+ curtype == TYPE_I ? "rb" : "r",
+ cp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
+ return;
+ }
+ for (i = 1; i < argc; i++) {
+ char **cpp;
+ glob_t gl;
+ int flags;
+
+ 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],
+ curtype == TYPE_I ? "rb" : "r",
+ tp, tp != argv[i] || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ continue;
+ }
+
+ memset(&gl, 0, sizeof(gl));
+ flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+ if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
+ warnx("%s: not found", argv[i]);
+ globfree(&gl);
+ continue;
+ }
+ for (cpp = gl.gl_pathv; 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,
+ curtype == TYPE_I ? "rb" : "r",
+ *cpp != tp || !interactive);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mput")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ globfree(&gl);
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+void
+reget(int argc, char **argv)
+{
+ getit(argc, argv, 1, curtype == TYPE_I ? "r+wb" : "r+w");
+}
+
+void
+get(int argc, char **argv)
+{
+ char *mode;
+
+ if (restart_point)
+ if (curtype == TYPE_I)
+ mode = "r+wb";
+ else
+ mode = "r+w";
+ else
+ if (curtype == TYPE_I)
+ mode = "wb";
+ else
+ mode = "w";
+
+ getit(argc, argv, 0, mode);
+}
+
+/*
+ * Receive one file.
+ */
+int
+getit(int argc, char **argv, int restartit, char *mode)
+{
+ int loc = 0;
+ int local_given = 1;
+ char *oldargv1, *oldargv2;
+
+ if (argc == 2) {
+ argc++;
+ local_given = 0;
+ argv[2] = argv[1];
+ loc++;
+ }
+ if ((argc < 2 && !another(&argc, &argv, "remote-file")) ||
+ (argc < 3 && !another(&argc, &argv, "local-file"))) {
+ printf("usage: %s remote-file [ local-file ]\n", argv[0]);
+ code = -1;
+ return (0);
+ }
+ oldargv1 = argv[1];
+ oldargv2 = argv[2];
+ if (!globulize(&argv[2])) {
+ code = -1;
+ return (0);
+ }
+ if (loc && mcase) {
+ char *tp = argv[1], *tp2, tmpbuf[MaxPathLen];
+
+ 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) {
+ warn("local: %s", argv[2]);
+ return (0);
+ }
+ restart_point = stbuf.st_size;
+ } else if (ret == 0) {
+ int overbose;
+ int cmdret;
+ int yy, mo, day, hour, min, sec;
+ struct tm *tm;
+
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+ cmdret = command("MDTM %s", argv[1]);
+ verbose = overbose;
+ if (cmdret != COMPLETE) {
+ printf("%s\n", reply_string);
+ return (0);
+ }
+ if (sscanf(reply_string,
+ "%*s %04d%02d%02d%02d%02d%02d",
+ &yy, &mo, &day, &hour, &min, &sec)
+ != 6) {
+ printf ("bad MDTM result\n");
+ return (0);
+ }
+
+ tm = gmtime(&stbuf.st_mtime);
+ tm->tm_mon++;
+ tm->tm_year += 1900;
+
+ if ((tm->tm_year > yy) ||
+ (tm->tm_year == yy &&
+ tm->tm_mon > mo) ||
+ (tm->tm_mon == mo &&
+ tm->tm_mday > day) ||
+ (tm->tm_mday == day &&
+ tm->tm_hour > hour) ||
+ (tm->tm_hour == hour &&
+ tm->tm_min > min) ||
+ (tm->tm_min == min &&
+ tm->tm_sec > sec))
+ return (1);
+ }
+ }
+
+ recvrequest("RETR", argv[2], argv[1], mode,
+ argv[1] != oldargv1 || argv[2] != oldargv2, local_given);
+ restart_point = 0;
+ return (0);
+}
+
+static int
+suspicious_filename(const char *fn)
+{
+ return strstr(fn, "../") != NULL || *fn == '/';
+}
+
+/*
+ * Get multiple files.
+ */
+void
+mget(int argc, char **argv)
+{
+ sighand oldintr;
+ int ch, ointer;
+ char *cp, *tp, *tp2, tmpbuf[MaxPathLen];
+
+ 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);
+ setjmp(jabort);
+ while ((cp = remglob(argv,proxy)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && suspicious_filename(cp))
+ printf("*** Suspicious filename: %s\n", cp);
+ if (mflag && confirm(argv[0], cp)) {
+ tp = cp;
+ if (mcase) {
+ for (tp2 = tmpbuf; (ch = *tp++);)
+ *tp2++ = isupper(ch) ? tolower(ch) : ch;
+ *tp2 = '\0';
+ tp = tmpbuf;
+ }
+ if (ntflag) {
+ tp = dotrans(tp);
+ }
+ if (mapflag) {
+ tp = domap(tp);
+ }
+ recvrequest("RETR", tp, cp,
+ curtype == TYPE_I ? "wb" : "w",
+ tp != cp || !interactive, 0);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with","mget")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ signal(SIGINT,oldintr);
+ mflag = 0;
+}
+
+char *
+remglob(char **argv, int doswitch)
+{
+ char temp[16];
+ static char buf[MaxPathLen];
+ static FILE *ftemp = NULL;
+ static char **args;
+ int oldverbose, oldhash;
+ char *cp, *mode;
+
+ if (!mflag) {
+ if (!doglob) {
+ args = NULL;
+ }
+ else {
+ if (ftemp) {
+ 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 fd;
+ strlcpy(temp, _PATH_TMP_XXX, sizeof(temp));
+ fd = mkstemp(temp);
+ if(fd < 0){
+ warn("unable to create temporary file %s", temp);
+ return NULL;
+ }
+ close(fd);
+ oldverbose = verbose, verbose = 0;
+ oldhash = hash, hash = 0;
+ if (doswitch) {
+ pswitch(!proxy);
+ }
+ for (mode = "w"; *++argv != NULL; mode = "a")
+ recvrequest ("NLST", temp, *argv, mode, 0, 0);
+ if (doswitch) {
+ pswitch(!proxy);
+ }
+ verbose = oldverbose; hash = oldhash;
+ ftemp = fopen(temp, "r");
+ unlink(temp);
+ if (ftemp == NULL) {
+ printf("can't find list of remote files, oops\n");
+ return (NULL);
+ }
+ }
+ while(fgets(buf, sizeof (buf), ftemp)) {
+ if ((cp = strchr(buf, '\n')) != NULL)
+ *cp = '\0';
+ if(!interactive && suspicious_filename(buf)){
+ printf("Ignoring remote globbed file `%s'\n", buf);
+ continue;
+ }
+ return buf;
+ }
+ fclose(ftemp);
+ ftemp = NULL;
+ return (NULL);
+}
+
+char *
+onoff(int bool)
+{
+
+ return (bool ? "on" : "off");
+}
+
+/*
+ * Show status.
+ */
+/*ARGSUSED*/
+void
+status(int argc, char **argv)
+{
+ int i;
+
+ if (connected)
+ printf("Connected to %s.\n", hostname);
+ else
+ printf("Not connected.\n");
+ if (!proxy) {
+ pswitch(1);
+ if (connected) {
+ printf("Connected for proxy commands to %s.\n", hostname);
+ }
+ else {
+ printf("No proxy connection.\n");
+ }
+ pswitch(0);
+ }
+ sec_status();
+ 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));
+ 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.
+ */
+/*VARARGS*/
+void
+setbell(int argc, char **argv)
+{
+
+ bell = !bell;
+ printf("Bell mode %s.\n", onoff(bell));
+ code = bell;
+}
+
+/*
+ * Turn on packet tracing.
+ */
+/*VARARGS*/
+void
+settrace(int argc, char **argv)
+{
+
+ trace = !trace;
+ printf("Packet tracing %s.\n", onoff(trace));
+ code = trace;
+}
+
+/*
+ * Toggle hash mark printing during transfers.
+ */
+/*VARARGS*/
+void
+sethash(int argc, char **argv)
+{
+
+ hash = !hash;
+ printf("Hash mark printing %s", onoff(hash));
+ code = hash;
+ if (hash)
+ printf(" (%d bytes/hash mark)", 1024);
+ printf(".\n");
+}
+
+/*
+ * Turn on printing of server echo's.
+ */
+/*VARARGS*/
+void
+setverbose(int argc, char **argv)
+{
+
+ verbose = !verbose;
+ printf("Verbose mode %s.\n", onoff(verbose));
+ code = verbose;
+}
+
+/*
+ * Toggle PORT cmd use before each data connection.
+ */
+/*VARARGS*/
+void
+setport(int argc, char **argv)
+{
+
+ sendport = !sendport;
+ printf("Use of PORT cmds %s.\n", onoff(sendport));
+ code = sendport;
+}
+
+/*
+ * Turn on interactive prompting
+ * during mget, mput, and mdelete.
+ */
+/*VARARGS*/
+void
+setprompt(int argc, char **argv)
+{
+
+ interactive = !interactive;
+ printf("Interactive mode %s.\n", onoff(interactive));
+ code = interactive;
+}
+
+/*
+ * Toggle metacharacter interpretation
+ * on local file names.
+ */
+/*VARARGS*/
+void
+setglob(int argc, char **argv)
+{
+
+ doglob = !doglob;
+ printf("Globbing %s.\n", onoff(doglob));
+ code = doglob;
+}
+
+/*
+ * Set debugging mode on/off and/or
+ * set level of debugging.
+ */
+/*VARARGS*/
+void
+setdebug(int argc, char **argv)
+{
+ int val;
+
+ if (argc > 1) {
+ val = atoi(argv[1]);
+ if (val < 0) {
+ printf("%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)
+ printf("CWD command not recognized, trying XCWD\n");
+ command("XCWD %s", argv[1]);
+ }
+}
+
+/*
+ * Set current working directory
+ * on local machine.
+ */
+void
+lcd(int argc, char **argv)
+{
+ char buf[MaxPathLen];
+
+ if (argc < 2)
+ argc++, argv[1] = home;
+ if (argc != 2) {
+ printf("usage: %s local-directory\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if (!globulize(&argv[1])) {
+ code = -1;
+ return;
+ }
+ if (chdir(argv[1]) < 0) {
+ warn("local: %s", argv[1]);
+ code = -1;
+ return;
+ }
+ if (getcwd(buf, sizeof(buf)) != NULL)
+ printf("Local directory now %s\n", buf);
+ else
+ warnx("getwd: %s", buf);
+ code = 0;
+}
+
+/*
+ * Delete a single file.
+ */
+void
+delete(int argc, char **argv)
+{
+
+ if (argc < 2 && !another(&argc, &argv, "remote-file")) {
+ printf("usage: %s remote-file\n", argv[0]);
+ code = -1;
+ return;
+ }
+ command("DELE %s", argv[1]);
+}
+
+/*
+ * Delete multiple files.
+ */
+void
+mdelete(int argc, char **argv)
+{
+ sighand oldintr;
+ 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);
+ setjmp(jabort);
+ while ((cp = remglob(argv,0)) != NULL) {
+ if (*cp == '\0') {
+ mflag = 0;
+ continue;
+ }
+ if (mflag && confirm(argv[0], cp)) {
+ command("DELE %s", cp);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", "mdelete")) {
+ mflag++;
+ }
+ interactive = ointer;
+ }
+ }
+ }
+ 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)
+ command("RNTO %s", argv[2]);
+}
+
+/*
+ * Get a directory listing
+ * of remote files.
+ */
+void
+ls(int argc, char **argv)
+{
+ char *cmd;
+
+ if (argc < 2)
+ argc++, argv[1] = NULL;
+ if (argc < 3)
+ argc++, argv[2] = "-";
+ 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], "-") && !globulize(&argv[2])) {
+ code = -1;
+ return;
+ }
+ if (strcmp(argv[2], "-") && *argv[2] != '|')
+ if (!globulize(&argv[2]) || !confirm("output to local-file:",
+ argv[2])) {
+ code = -1;
+ return;
+ }
+ recvrequest(cmd, argv[2], argv[1], "w", 0, 1);
+}
+
+/*
+ * Get a directory listing
+ * of multiple remote files.
+ */
+void
+mls(int argc, char **argv)
+{
+ sighand oldintr;
+ int ointer, i;
+ char *cmd, mode[1], *dest;
+
+ 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 (!globulize(&dest) ||
+ !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);
+ setjmp(jabort);
+ for (i = 1; mflag && i < argc-1; ++i) {
+ *mode = (i == 1) ? 'w' : 'a';
+ recvrequest(cmd, dest, argv[i], mode, 0, 1);
+ if (!mflag && fromatty) {
+ ointer = interactive;
+ interactive = 1;
+ if (confirm("Continue with", argv[0])) {
+ mflag ++;
+ }
+ interactive = ointer;
+ }
+ }
+ signal(SIGINT, oldintr);
+ mflag = 0;
+}
+
+/*
+ * Do a shell escape
+ */
+/*ARGSUSED*/
+void
+shell(int argc, char **argv)
+{
+ pid_t pid;
+ RETSIGTYPE (*old1)(), (*old2)();
+ char shellnam[40], *shell, *namep;
+ int status;
+
+ old1 = signal (SIGINT, SIG_IGN);
+ old2 = signal (SIGQUIT, SIG_IGN);
+ if ((pid = fork()) == 0) {
+ for (pid = 3; pid < 20; pid++)
+ close(pid);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ shell = getenv("SHELL");
+ if (shell == NULL)
+ shell = _PATH_BSHELL;
+ namep = strrchr(shell,'/');
+ if (namep == NULL)
+ namep = shell;
+ snprintf (shellnam, sizeof(shellnam),
+ "-%s", ++namep);
+ if (strcmp(namep, "sh") != 0)
+ shellnam[0] = '+';
+ if (debug) {
+ printf ("%s\n", shell);
+ fflush (stdout);
+ }
+ if (argc > 1) {
+ execl(shell,shellnam,"-c",altarg,(char *)0);
+ }
+ else {
+ execl(shell,shellnam,(char *)0);
+ }
+ warn("%s", shell);
+ code = -1;
+ exit(1);
+ }
+ if (pid > 0)
+ while (waitpid(-1, &status, 0) != pid)
+ ;
+ signal(SIGINT, old1);
+ signal(SIGQUIT, old2);
+ if (pid == -1) {
+ warn("%s", "Try again later");
+ code = -1;
+ }
+ else {
+ code = 0;
+ }
+}
+
+/*
+ * Send new user information (re-login)
+ */
+void
+user(int argc, char **argv)
+{
+ char acct[80];
+ int n, aflag = 0;
+ char tmp[256];
+
+ if (argc < 2)
+ 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 ) {
+ des_read_pw_string (tmp,
+ sizeof(tmp),
+ "Password: ", 0);
+ argv[2] = tmp;
+ argc++;
+ }
+ n = command("PASS %s", argv[2]);
+ }
+ if (n == CONTINUE) {
+ if (argc < 4) {
+ printf("Account: "); fflush(stdout);
+ fgets(acct, sizeof(acct) - 1, stdin);
+ acct[strlen(acct) - 1] = '\0';
+ argv[3] = acct; argc++;
+ }
+ n = command("ACCT %s", argv[3]);
+ aflag++;
+ }
+ if (n != COMPLETE) {
+ fprintf(stdout, "Login failed.\n");
+ return;
+ }
+ if (!aflag && argc == 4) {
+ command("ACCT %s", argv[3]);
+ }
+}
+
+/*
+ * Print working directory.
+ */
+/*VARARGS*/
+void
+pwd(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ /*
+ * If we aren't verbose, this doesn't do anything!
+ */
+ verbose = 1;
+ if (command("PWD") == ERROR && code == 500) {
+ printf("PWD command not recognized, trying XPWD\n");
+ 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)
+ printf("MKD command not recognized, trying XMKD\n");
+ 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)
+ printf("RMD command not recognized, trying XRMD\n");
+ 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.
+ */
+void
+quote1(char *initial, int argc, char **argv)
+{
+ int i;
+ char buf[BUFSIZ]; /* must be >= sizeof(line) */
+
+ strlcpy(buf, initial, sizeof(buf));
+ for(i = 1; i < argc; i++) {
+ if(i > 1)
+ strlcat(buf, " ", sizeof(buf));
+ strlcat(buf, argv[i], sizeof(buf));
+ }
+ if (command("%s", buf) == PRELIM) {
+ while (getreply(0) == PRELIM)
+ continue;
+ }
+}
+
+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;
+ }
+ command("SITE CHMOD %s %s", argv[1], argv[2]);
+}
+
+void
+do_umask(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
+ verbose = oldverbose;
+}
+
+void
+ftp_idle(int argc, char **argv)
+{
+ int oldverbose = verbose;
+
+ verbose = 1;
+ 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;
+ command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
+ verbose = oldverbose;
+}
+
+/*
+ * Terminate session and exit.
+ */
+/*VARARGS*/
+void
+quit(int argc, char **argv)
+{
+
+ if (connected)
+ disconnect(0, 0);
+ pswitch(1);
+ if (connected) {
+ disconnect(0, 0);
+ }
+ exit(0);
+}
+
+/*
+ * Terminate session, but don't exit.
+ */
+void
+disconnect(int argc, char **argv)
+{
+
+ if (!connected)
+ return;
+ command("QUIT");
+ if (cout) {
+ fclose(cout);
+ }
+ cout = NULL;
+ connected = 0;
+ sec_end();
+ data = -1;
+ if (!proxy) {
+ macnum = 0;
+ }
+}
+
+int
+confirm(char *cmd, char *file)
+{
+ char line[BUFSIZ];
+
+ if (!interactive)
+ return (1);
+ printf("%s %s? ", cmd, file);
+ fflush(stdout);
+ if (fgets(line, sizeof line, stdin) == NULL)
+ return (0);
+ return (*line == 'y' || *line == 'Y');
+}
+
+void
+fatal(char *msg)
+{
+
+ errx(1, "%s", msg);
+}
+
+/*
+ * 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.
+ */
+int
+globulize(char **cpp)
+{
+ glob_t gl;
+ int flags;
+
+ if (!doglob)
+ return (1);
+
+ flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+ memset(&gl, 0, sizeof(gl));
+ if (glob(*cpp, flags, NULL, &gl) ||
+ gl.gl_pathc == 0) {
+ warnx("%s: not found", *cpp);
+ globfree(&gl);
+ return (0);
+ }
+ *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */
+ globfree(&gl);
+ return (1);
+}
+
+void
+account(int argc, char **argv)
+{
+ char acct[50];
+
+ if (argc > 1) {
+ ++argv;
+ --argc;
+ strlcpy (acct, *argv, sizeof(acct));
+ while (argc > 1) {
+ --argc;
+ ++argv;
+ strlcat(acct, *argv, sizeof(acct));
+ }
+ }
+ else {
+ des_read_pw_string(acct, sizeof(acct), "Account:", 0);
+ }
+ command("ACCT %s", acct);
+}
+
+jmp_buf abortprox;
+
+static RETSIGTYPE
+proxabort(int sig)
+{
+
+ if (!proxy) {
+ pswitch(1);
+ }
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ longjmp(abortprox,1);
+}
+
+void
+doproxy(int argc, char **argv)
+{
+ struct cmd *c;
+ RETSIGTYPE (*oldintr)();
+
+ 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");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (!c->c_proxy) {
+ printf("?Invalid proxy command\n");
+ fflush(stdout);
+ code = -1;
+ return;
+ }
+ if (setjmp(abortprox)) {
+ code = -1;
+ return;
+ }
+ oldintr = signal(SIGINT, proxabort);
+ pswitch(1);
+ if (c->c_conn && !connected) {
+ printf("Not connected\n");
+ fflush(stdout);
+ pswitch(0);
+ signal(SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ (*c->c_handler)(argc-1, argv+1);
+ if (connected) {
+ proxflag = 1;
+ }
+ else {
+ proxflag = 0;
+ }
+ pswitch(0);
+ signal(SIGINT, oldintr);
+}
+
+void
+setcase(int argc, char **argv)
+{
+
+ mcase = !mcase;
+ printf("Case mapping %s.\n", onoff(mcase));
+ code = mcase;
+}
+
+void
+setcr(int argc, char **argv)
+{
+
+ 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;
+ strlcpy (ntin, argv[1], 17);
+ if (argc == 2) {
+ ntout[0] = '\0';
+ return;
+ }
+ strlcpy (ntout, argv[2], 17);
+}
+
+char *
+dotrans(char *name)
+{
+ static char new[MaxPathLen];
+ char *cp1, *cp2 = new;
+ int i, ostop, found;
+
+ for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
+ continue;
+ for (cp1 = name; *cp1; cp1++) {
+ found = 0;
+ for (i = 0; *(ntin + i) && i < 16; 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 = strchr(altarg, ' ');
+ if (proxy) {
+ while(*++cp == ' ')
+ continue;
+ altarg = cp;
+ cp = strchr(altarg, ' ');
+ }
+ *cp = '\0';
+ strlcpy(mapin, altarg, MaxPathLen);
+ while (*++cp == ' ')
+ continue;
+ strlcpy(mapout, cp, MaxPathLen);
+}
+
+char *
+domap(char *name)
+{
+ static char new[MaxPathLen];
+ 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)) {
+ toks[toknum = *cp2 - '1']++;
+ 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
+setpassive(int argc, char **argv)
+{
+
+ passivemode = !passivemode;
+ printf("Passive mode %s.\n", onoff(passivemode));
+ code = passivemode;
+}
+
+void
+setsunique(int argc, char **argv)
+{
+
+ sunique = !sunique;
+ printf("Store unique %s.\n", onoff(sunique));
+ code = sunique;
+}
+
+void
+setrunique(int argc, char **argv)
+{
+
+ runique = !runique;
+ printf("Receive unique %s.\n", onoff(runique));
+ code = runique;
+}
+
+/* change directory to perent directory */
+void
+cdup(int argc, char **argv)
+{
+
+ if (command("CDUP") == ERROR && code == 500) {
+ if (verbose)
+ printf("CDUP command not recognized, trying XCUP\n");
+ 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(int argc, char **argv)
+{
+
+ 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");
+ }
+ strlcpy(macros[macnum].mac_name,
+ argv[1],
+ sizeof(macros[macnum].mac_name));
+ 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+4096) {
+ 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;
+ }
+ }
+}
+
+/*
+ * 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;
+ }
+ 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 reomte machine
+ */
+void
+rmtstatus(int argc, char **argv)
+{
+
+ 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, curtype == TYPE_I ? "wb" : "w"))
+ printf("Local file \"%s\" is newer than remote file \"%s\"\n",
+ argv[2], argv[1]);
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/cmdtab.c b/crypto/heimdal/appl/ftp/ftp/cmdtab.c
new file mode 100644
index 0000000..5dc96ef
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/cmdtab.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+#include "ftp_locl.h"
+
+/*
+ * User FTP -- Command Tables.
+ */
+
+char accounthelp[] = "send account command to remote server";
+char appendhelp[] = "append to a file";
+char asciihelp[] = "set ascii transfer type";
+char beephelp[] = "beep when command completed";
+char binaryhelp[] = "set binary transfer type";
+char casehelp[] = "toggle mget upper/lower case id mapping";
+char cdhelp[] = "change remote working directory";
+char cduphelp[] = "change remote working directory to parent directory";
+char chmodhelp[] = "change file permissions of remote file";
+char connecthelp[] = "connect to remote tftp";
+char crhelp[] = "toggle carriage return stripping on ascii gets";
+char deletehelp[] = "delete remote file";
+char debughelp[] = "toggle/set debugging mode";
+char dirhelp[] = "list contents of remote directory";
+char disconhelp[] = "terminate ftp session";
+char domachelp[] = "execute macro";
+char formhelp[] = "set file transfer format";
+char globhelp[] = "toggle metacharacter expansion of local file names";
+char hashhelp[] = "toggle printing `#' for each buffer transferred";
+char helphelp[] = "print local help information";
+char idlehelp[] = "get (set) idle timer on remote side";
+char lcdhelp[] = "change local working directory";
+char lshelp[] = "list contents of remote directory";
+char macdefhelp[] = "define a macro";
+char mdeletehelp[] = "delete multiple files";
+char mdirhelp[] = "list contents of multiple remote directories";
+char mgethelp[] = "get multiple files";
+char mkdirhelp[] = "make directory on the remote machine";
+char mlshelp[] = "list contents of multiple remote directories";
+char modtimehelp[] = "show last modification time of remote file";
+char modehelp[] = "set file transfer mode";
+char mputhelp[] = "send multiple files";
+char newerhelp[] = "get file if remote file is newer than local file ";
+char nlisthelp[] = "nlist contents of remote directory";
+char nmaphelp[] = "set templates for default file name mapping";
+char ntranshelp[] = "set translation table for default file name mapping";
+char porthelp[] = "toggle use of PORT cmd for each data connection";
+char prompthelp[] = "force interactive prompting on multiple commands";
+char proxyhelp[] = "issue command on alternate connection";
+char pwdhelp[] = "print working directory on remote machine";
+char quithelp[] = "terminate ftp session and exit";
+char quotehelp[] = "send arbitrary ftp command";
+char receivehelp[] = "receive file";
+char regethelp[] = "get file restarting at end of local file";
+char remotehelp[] = "get help from remote server";
+char renamehelp[] = "rename file";
+char restarthelp[]= "restart file transfer at bytecount";
+char rmdirhelp[] = "remove directory on the remote machine";
+char rmtstatushelp[]="show status of remote machine";
+char runiquehelp[] = "toggle store unique for local files";
+char resethelp[] = "clear queued command replies";
+char sendhelp[] = "send one file";
+char passivehelp[] = "enter passive transfer mode";
+char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information";
+char shellhelp[] = "escape to the shell";
+char sizecmdhelp[] = "show size of remote file";
+char statushelp[] = "show current status";
+char structhelp[] = "set file transfer structure";
+char suniquehelp[] = "toggle store unique on remote machine";
+char systemhelp[] = "show remote system type";
+char tenexhelp[] = "set tenex file transfer type";
+char tracehelp[] = "toggle packet tracing";
+char typehelp[] = "set file transfer type";
+char umaskhelp[] = "get (set) umask on remote side";
+char userhelp[] = "send new user information";
+char verbosehelp[] = "toggle verbose mode";
+
+char prothelp[] = "set protection level";
+#ifdef KRB4
+char kauthhelp[] = "get remote tokens";
+char klisthelp[] = "show remote tickets";
+char kdestroyhelp[] = "destroy remote tickets";
+char krbtkfilehelp[] = "set filename of remote tickets";
+char afsloghelp[] = "obtain remote AFS tokens";
+#endif
+
+struct cmd cmdtab[] = {
+ { "!", shellhelp, 0, 0, 0, shell },
+ { "$", domachelp, 1, 0, 0, domacro },
+ { "account", accounthelp, 0, 1, 1, account},
+ { "append", appendhelp, 1, 1, 1, put },
+ { "ascii", asciihelp, 0, 1, 1, setascii },
+ { "bell", beephelp, 0, 0, 0, setbell },
+ { "binary", binaryhelp, 0, 1, 1, setbinary },
+ { "bye", quithelp, 0, 0, 0, quit },
+ { "case", casehelp, 0, 0, 1, setcase },
+ { "cd", cdhelp, 0, 1, 1, cd },
+ { "cdup", cduphelp, 0, 1, 1, cdup },
+ { "chmod", chmodhelp, 0, 1, 1, do_chmod },
+ { "close", disconhelp, 0, 1, 1, disconnect },
+ { "cr", crhelp, 0, 0, 0, setcr },
+ { "delete", deletehelp, 0, 1, 1, delete },
+ { "debug", debughelp, 0, 0, 0, setdebug },
+ { "dir", dirhelp, 1, 1, 1, ls },
+ { "disconnect", disconhelp, 0, 1, 1, disconnect },
+ { "form", formhelp, 0, 1, 1, setform },
+ { "get", receivehelp, 1, 1, 1, get },
+ { "glob", globhelp, 0, 0, 0, setglob },
+ { "hash", hashhelp, 0, 0, 0, sethash },
+ { "help", helphelp, 0, 0, 1, help },
+ { "idle", idlehelp, 0, 1, 1, ftp_idle },
+ { "image", binaryhelp, 0, 1, 1, setbinary },
+ { "lcd", lcdhelp, 0, 0, 0, lcd },
+ { "ls", lshelp, 1, 1, 1, ls },
+ { "macdef", macdefhelp, 0, 0, 0, macdef },
+ { "mdelete", mdeletehelp, 1, 1, 1, mdelete },
+ { "mdir", mdirhelp, 1, 1, 1, mls },
+ { "mget", mgethelp, 1, 1, 1, mget },
+ { "mkdir", mkdirhelp, 0, 1, 1, makedir },
+ { "mls", mlshelp, 1, 1, 1, mls },
+ { "mode", modehelp, 0, 1, 1, setftmode },
+ { "modtime", modtimehelp, 0, 1, 1, modtime },
+ { "mput", mputhelp, 1, 1, 1, mput },
+ { "newer", newerhelp, 1, 1, 1, newer },
+ { "nmap", nmaphelp, 0, 0, 1, setnmap },
+ { "nlist", nlisthelp, 1, 1, 1, ls },
+ { "ntrans", ntranshelp, 0, 0, 1, setntrans },
+ { "open", connecthelp, 0, 0, 1, setpeer },
+ { "passive", passivehelp, 0, 0, 0, setpassive },
+ { "prompt", prompthelp, 0, 0, 0, setprompt },
+ { "proxy", proxyhelp, 0, 0, 1, doproxy },
+ { "sendport", porthelp, 0, 0, 0, setport },
+ { "put", sendhelp, 1, 1, 1, put },
+ { "pwd", pwdhelp, 0, 1, 1, pwd },
+ { "quit", quithelp, 0, 0, 0, quit },
+ { "quote", quotehelp, 1, 1, 1, quote },
+ { "recv", receivehelp, 1, 1, 1, get },
+ { "reget", regethelp, 1, 1, 1, reget },
+ { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus },
+ { "rhelp", remotehelp, 0, 1, 1, rmthelp },
+ { "rename", renamehelp, 0, 1, 1, renamefile },
+ { "reset", resethelp, 0, 1, 1, reset },
+ { "restart", restarthelp, 1, 1, 1, restart },
+ { "rmdir", rmdirhelp, 0, 1, 1, removedir },
+ { "runique", runiquehelp, 0, 0, 1, setrunique },
+ { "send", sendhelp, 1, 1, 1, put },
+ { "site", sitehelp, 0, 1, 1, site },
+ { "size", sizecmdhelp, 1, 1, 1, sizecmd },
+ { "status", statushelp, 0, 0, 1, status },
+ { "struct", structhelp, 0, 1, 1, setstruct },
+ { "system", systemhelp, 0, 1, 1, syst },
+ { "sunique", suniquehelp, 0, 0, 1, setsunique },
+ { "tenex", tenexhelp, 0, 1, 1, settenex },
+ { "trace", tracehelp, 0, 0, 0, settrace },
+ { "type", typehelp, 0, 1, 1, settype },
+ { "user", userhelp, 0, 1, 1, user },
+ { "umask", umaskhelp, 0, 1, 1, do_umask },
+ { "verbose", verbosehelp, 0, 0, 0, setverbose },
+ { "?", helphelp, 0, 0, 1, help },
+
+ { "prot", prothelp, 0, 1, 0, sec_prot },
+#ifdef KRB4
+ { "kauth", kauthhelp, 0, 1, 0, kauth },
+ { "klist", klisthelp, 0, 1, 0, klist },
+ { "kdestroy", kdestroyhelp, 0, 1, 0, kdestroy },
+ { "krbtkfile", krbtkfilehelp, 0, 1, 0, krbtkfile },
+ { "afslog", afsloghelp, 0, 1, 0, afslog },
+#endif
+
+ { 0 },
+};
+
+int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1;
diff --git a/crypto/heimdal/appl/ftp/ftp/domacro.c b/crypto/heimdal/appl/ftp/ftp/domacro.c
new file mode 100644
index 0000000..d91660d
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/domacro.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1985, 1993, 1994
+ * 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.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: domacro.c,v 1.7 1999/09/16 20:37:29 assar Exp $");
+
+void
+domacro(int argc, char **argv)
+{
+ int i, j, count = 2, loopflg = 0;
+ char *cp1, *cp2, line2[200];
+ 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;
+ }
+ strlcpy(line2, line, sizeof(line2));
+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) {
+ strcpy(cp2, argv[j+1]);
+ cp2 += strlen(argv[j+1]);
+ }
+ break;
+ }
+ if (*(cp1+1) == 'i') {
+ loopflg = 1;
+ cp1++;
+ if (count < argc) {
+ strcpy(cp2, argv[count]);
+ cp2 += strlen(argv[count]);
+ }
+ break;
+ }
+ /* intentional drop through */
+ default:
+ *cp2++ = *cp1;
+ break;
+ }
+ if (*cp1 != '\0') {
+ cp1++;
+ }
+ }
+ *cp2 = '\0';
+ makeargv();
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ code = -1;
+ }
+ else if (c == 0) {
+ 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);
+ }
+ (*c->c_handler)(margc, margv);
+ if (bell && c->c_bell) {
+ putchar('\007');
+ }
+ strcpy(line, line2);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ if (cp1 != macros[i].mac_end) {
+ cp1++;
+ }
+ }
+ if (loopflg && ++count < argc) {
+ goto TOP;
+ }
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/extern.h b/crypto/heimdal/appl/ftp/ftp/extern.h
new file mode 100644
index 0000000..d488ecd
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/extern.h
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 1994 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.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 10/9/94
+ */
+
+/* $Id: extern.h,v 1.18 1999/10/28 20:49:10 assar Exp $ */
+
+#include <setjmp.h>
+#include <stdlib.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+void abort_remote (FILE *);
+void abortpt (int);
+void abortrecv (int);
+void account (int, char **);
+int another (int *, char ***, char *);
+void blkfree (char **);
+void cd (int, char **);
+void cdup (int, char **);
+void changetype (int, int);
+void cmdabort (int);
+void cmdscanner (int);
+int command (char *fmt, ...);
+int confirm (char *, char *);
+FILE *dataconn (const char *);
+void delete (int, char **);
+void disconnect (int, char **);
+void do_chmod (int, char **);
+void do_umask (int, char **);
+void domacro (int, char **);
+char *domap (char *);
+void doproxy (int, char **);
+char *dotrans (char *);
+int empty (fd_set *, int);
+void fatal (char *);
+void get (int, char **);
+struct cmd *getcmd (char *);
+int getit (int, char **, int, char *);
+int getreply (int);
+int globulize (char **);
+char *gunique (char *);
+void help (int, char **);
+char *hookup (const char *, int);
+void ftp_idle (int, char **);
+int initconn (void);
+void intr (int);
+void lcd (int, char **);
+int login (char *);
+RETSIGTYPE lostpeer (int);
+void ls (int, char **);
+void macdef (int, char **);
+void makeargv (void);
+void makedir (int, char **);
+void mdelete (int, char **);
+void mget (int, char **);
+void mls (int, char **);
+void modtime (int, char **);
+void mput (int, char **);
+char *onoff (int);
+void newer (int, char **);
+void proxtrans (char *, char *, char *);
+void psabort (int);
+void pswitch (int);
+void ptransfer (char *, long, struct timeval *, struct timeval *);
+void put (int, char **);
+void pwd (int, char **);
+void quit (int, char **);
+void quote (int, char **);
+void quote1 (char *, int, char **);
+void recvrequest (char *, char *, char *, char *, int, int);
+void reget (int, char **);
+char *remglob (char **, int);
+void removedir (int, char **);
+void renamefile (int, char **);
+void reset (int, char **);
+void restart (int, char **);
+void rmthelp (int, char **);
+void rmtstatus (int, char **);
+int ruserpass (char *, char **, char **, char **);
+void sendrequest (char *, char *, char *, char *, int);
+void setascii (int, char **);
+void setbell (int, char **);
+void setbinary (int, char **);
+void setcase (int, char **);
+void setcr (int, char **);
+void setdebug (int, char **);
+void setform (int, char **);
+void setftmode (int, char **);
+void setglob (int, char **);
+void sethash (int, char **);
+void setnmap (int, char **);
+void setntrans (int, char **);
+void setpassive (int, char **);
+void setpeer (int, char **);
+void setport (int, char **);
+void setprompt (int, char **);
+void setrunique (int, char **);
+void setstruct (int, char **);
+void setsunique (int, char **);
+void settenex (int, char **);
+void settrace (int, char **);
+void settype (int, char **);
+void setverbose (int, char **);
+void shell (int, char **);
+void site (int, char **);
+void sizecmd (int, char **);
+char *slurpstring (void);
+void status (int, char **);
+void syst (int, char **);
+void tvsub (struct timeval *, struct timeval *, struct timeval *);
+void user (int, char **);
+
+extern jmp_buf abortprox;
+extern int abrtflag;
+extern struct cmd cmdtab[];
+extern FILE *cout;
+extern int data;
+extern char *home;
+extern jmp_buf jabort;
+extern int proxy;
+extern char reply_string[];
+extern off_t restart_point;
+extern int NCMDS;
+
+extern char username[32];
+extern char myhostname[];
+extern char *mydomain;
+
+void afslog (int, char **);
+void kauth (int, char **);
+void kdestroy (int, char **);
+void klist (int, char **);
+void krbtkfile (int, char **);
diff --git a/crypto/heimdal/appl/ftp/ftp/ftp.1 b/crypto/heimdal/appl/ftp/ftp/ftp.1
new file mode 100644
index 0000000..e5c21f0
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/ftp.1
@@ -0,0 +1,1193 @@
+.\" $NetBSD: ftp.1,v 1.11 1995/09/08 01:06:24 tls Exp $
+.\"
+.\" Copyright (c) 1985, 1989, 1990, 1993
+.\" 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.
+.\"
+.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
+.\"
+.Dd April 27, 1996
+.Dt FTP 1
+.Os BSD 4.2
+.Sh NAME
+.Nm ftp
+.Nd
+.Tn ARPANET
+file transfer program
+.Sh SYNOPSIS
+.Nm ftp
+.Op Fl t
+.Op Fl v
+.Op Fl d
+.Op Fl i
+.Op Fl n
+.Op Fl g
+.Op Fl p
+.Op Ar host
+.Sh DESCRIPTION
+.Nm Ftp
+is the user interface to the
+.Tn ARPANET
+standard File Transfer Protocol.
+The program allows a user to transfer files to and from a
+remote network site.
+.Pp
+Modifications has been made so that it almost follows the ftpsec
+Internet draft.
+.Pp
+Options may be specified at the command line, or to the
+command interpreter.
+.Bl -tag -width flag
+.It Fl t
+Enables packet tracing.
+.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 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 below) 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 i
+Turns off interactive prompting during
+multiple file transfers.
+.It Fl p
+Turn on passive mode.
+.It Fl d
+Enables debugging.
+.It Fl g
+Disables file name globbing.
+.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
+sytem 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 \- .
+As a security measure, remotely globbed files that starts with
+.Sq /
+or contains
+.Sq ../ ,
+will not be automatically received. If you have interactive prompting
+turned off, these filenames will be ignored. 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
+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 passive
+Toggle passive mode. If passive mode is turned on
+(default is off), the ftp client will
+send a
+.Dv PASV
+command for all data connections instead of the usual
+.Dv PORT
+command. The
+.Dv PASV
+command requests that the remote server open a port for the data connection
+and return the address of that port. The remote server listens on that
+port and the client connects to it. When using the more traditional
+.Dv PORT
+command, the client listens on a port and sends that address to the remote
+server, who connects back to it. Passive mode is useful when using
+.Nm ftp
+through a gateway router or host that controls the directionality of
+traffic.
+(Note that though ftp servers are required to support the
+.Dv PASV
+command by RFC 1123, some do not.)
+.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
+The following command can be used with ftpsec-aware servers.
+.Bl -tag -width Fl
+.It Xo
+.Ic prot
+.Ar clear |
+.Ar safe |
+.Ar confidential |
+.Ar private
+.Xc
+Set the data protection level to the requested level.
+.El
+.Pp
+The following command can be used with ftp servers that has
+implemented the KAUTH site command.
+.Bl -tag -width Fl
+.It Ic kauth Op Ar principal
+Obtain remote tickets.
+.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 THE .netrc FILE
+The
+.Pa .netrc
+file contains login and initialization information
+used by the auto-login process.
+It resides in the user's home directory.
+The following tokens are recognized; they may be separated by spaces,
+tabs, or new-lines:
+.Bl -tag -width password
+.It Ic machine Ar name
+Identify a remote machine
+.Ar name .
+The auto-login process searches the
+.Pa .netrc
+file for a
+.Ic machine
+token that matches the remote machine specified on the
+.Nm ftp
+command line or as an
+.Ic open
+command argument.
+Once a match is made, the subsequent
+.Pa .netrc
+tokens are processed,
+stopping when the end of file is reached or another
+.Ic machine
+or a
+.Ic default
+token is encountered.
+.It Ic default
+This is the same as
+.Ic machine
+.Ar name
+except that
+.Ic default
+matches any name.
+There can be only one
+.Ic default
+token, and it must be after all
+.Ic machine
+tokens.
+This is normally used as:
+.Pp
+.Dl default login anonymous password user@site
+.Pp
+thereby giving the user
+.Ar automatic
+anonymous ftp login to
+machines not specified in
+.Pa .netrc .
+This can be overridden
+by using the
+.Fl n
+flag to disable auto-login.
+.It Ic login Ar name
+Identify a user on the remote machine.
+If this token is present, the auto-login process will initiate
+a login using the specified
+.Ar name .
+.It Ic password Ar string
+Supply a password.
+If this token is present, the auto-login process will supply the
+specified string if the remote server requires a password as part
+of the login process.
+Note that if this token is present in the
+.Pa .netrc
+file for any user other
+than
+.Ar anonymous ,
+.Nm ftp
+will abort the auto-login process if the
+.Pa .netrc
+is readable by
+anyone besides the user.
+.It Ic account Ar string
+Supply an additional account password.
+If this token is present, the auto-login process will supply the
+specified string if the remote server requires an additional
+account password, or the auto-login process will initiate an
+.Dv ACCT
+command if it does not.
+.It Ic macdef Ar name
+Define a macro.
+This token functions like the
+.Nm ftp
+.Ic macdef
+command functions.
+A macro is defined with the specified name; its contents begin with the
+next
+.Pa .netrc
+line and continue until a null line (consecutive new-line
+characters) is encountered.
+If a macro named
+.Ic init
+is defined, it is automatically executed as the last step in the
+auto-login process.
+.El
+.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 ,
+.%T RFC2228
+.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.
diff --git a/crypto/heimdal/appl/ftp/ftp/ftp.c b/crypto/heimdal/appl/ftp/ftp/ftp.c
new file mode 100644
index 0000000..2e7a9dd
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/ftp.c
@@ -0,0 +1,1746 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+#include "ftp_locl.h"
+RCSID ("$Id: ftp.c,v 1.63 2000/01/08 07:43:47 assar Exp $");
+
+struct sockaddr_storage hisctladdr_ss;
+struct sockaddr *hisctladdr = (struct sockaddr *)&hisctladdr_ss;
+struct sockaddr_storage data_addr_ss;
+struct sockaddr *data_addr = (struct sockaddr *)&data_addr_ss;
+struct sockaddr_storage myctladdr_ss;
+struct sockaddr *myctladdr = (struct sockaddr *)&myctladdr_ss;
+int data = -1;
+int abrtflag = 0;
+jmp_buf ptabort;
+int ptabflg;
+int ptflag = 0;
+off_t restart_point = 0;
+
+
+FILE *cin, *cout;
+
+typedef void (*sighand) (int);
+
+char *
+hookup (const char *host, int port)
+{
+ static char hostnamebuf[MaxHostNameLen];
+ struct addrinfo *ai, *a;
+ struct addrinfo hints;
+ int error;
+ char portstr[NI_MAXSERV];
+ int len;
+ int s;
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ hints.ai_flags = AI_CANONNAME;
+
+ snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
+
+ error = getaddrinfo (host, portstr, &hints, &ai);
+ if (error) {
+ warnx ("%s: %s", host, gai_strerror(error));
+ code = -1;
+ return NULL;
+ }
+ strlcpy (hostnamebuf, host, sizeof(hostnamebuf));
+ hostname = hostnamebuf;
+
+ for (a = ai; a != NULL; a = a->ai_next) {
+ s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+ if (s < 0)
+ continue;
+
+ if (a->ai_canonname != NULL)
+ strlcpy (hostnamebuf, a->ai_canonname, sizeof(hostnamebuf));
+
+ memcpy (hisctladdr, a->ai_addr, a->ai_addrlen);
+
+ error = connect (s, a->ai_addr, a->ai_addrlen);
+ if (error < 0) {
+ char addrstr[256];
+
+ if (getnameinfo (a->ai_addr, a->ai_addrlen,
+ addrstr, sizeof(addrstr),
+ NULL, 0, NI_NUMERICHOST) != 0)
+ strlcpy (addrstr, "unknown address", sizeof(addrstr));
+
+ warn ("connect %s", addrstr);
+ close (s);
+ continue;
+ }
+ break;
+ }
+ freeaddrinfo (ai);
+ if (error < 0) {
+ warnx ("failed to contact %s", host);
+ code = -1;
+ return NULL;
+ }
+
+ len = sizeof(myctladdr_ss);
+ if (getsockname (s, myctladdr, &len) < 0) {
+ warn ("getsockname");
+ code = -1;
+ close (s);
+ return NULL;
+ }
+#ifdef IPTOS_LOWDELAY
+ socket_set_tos (s, IPTOS_LOWDELAY);
+#endif
+ cin = fdopen (s, "r");
+ cout = fdopen (s, "w");
+ if (cin == NULL || cout == NULL) {
+ warnx ("fdopen failed.");
+ if (cin)
+ fclose (cin);
+ if (cout)
+ fclose (cout);
+ code = -1;
+ goto bad;
+ }
+ if (verbose)
+ printf ("Connected to %s.\n", hostname);
+ if (getreply (0) > 2) { /* read startup message from server */
+ if (cin)
+ fclose (cin);
+ if (cout)
+ fclose (cout);
+ code = -1;
+ goto bad;
+ }
+#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
+ {
+ int on = 1;
+
+ if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
+ < 0 && debug) {
+ warn ("setsockopt");
+ }
+ }
+#endif /* SO_OOBINLINE */
+
+ return (hostname);
+bad:
+ close (s);
+ return NULL;
+}
+
+int
+login (char *host)
+{
+ char tmp[80];
+ char defaultpass[128];
+ char *user, *pass, *acct;
+ int n, aflag = 0;
+
+ char *myname = NULL;
+ struct passwd *pw = k_getpwuid(getuid());
+
+ if (pw != NULL)
+ myname = pw->pw_name;
+
+ user = pass = acct = 0;
+
+ if(sec_login(host))
+ printf("\n*** Using plaintext user and password ***\n\n");
+ else{
+ printf("Authentication successful.\n\n");
+ }
+
+ if (ruserpass (host, &user, &pass, &acct) < 0) {
+ code = -1;
+ return (0);
+ }
+ while (user == NULL) {
+ if (myname)
+ printf ("Name (%s:%s): ", host, myname);
+ else
+ printf ("Name (%s): ", host);
+ fgets (tmp, sizeof (tmp) - 1, stdin);
+ tmp[strlen (tmp) - 1] = '\0';
+ if (*tmp == '\0')
+ user = myname;
+ else
+ user = tmp;
+ }
+ strlcpy(username, user, sizeof(username));
+ n = command("USER %s", user);
+ if (n == CONTINUE) {
+ if(sec_complete)
+ pass = myname;
+ else if (pass == NULL) {
+ char prompt[128];
+ if(myname &&
+ (!strcmp(user, "ftp") || !strcmp(user, "anonymous"))){
+ snprintf(defaultpass, sizeof(defaultpass),
+ "%s@%s", myname, mydomain);
+ snprintf(prompt, sizeof(prompt),
+ "Password (%s): ", defaultpass);
+ }else{
+ *defaultpass = '\0';
+ snprintf(prompt, sizeof(prompt), "Password: ");
+ }
+ pass = defaultpass;
+ des_read_pw_string (tmp, sizeof (tmp), prompt, 0);
+ if (tmp[0])
+ pass = tmp;
+ }
+ n = command ("PASS %s", pass);
+ }
+ if (n == CONTINUE) {
+ aflag++;
+ acct = tmp;
+ des_read_pw_string (acct, 128, "Account:", 0);
+ n = command ("ACCT %s", acct);
+ }
+ if (n != COMPLETE) {
+ warnx ("Login failed.");
+ return (0);
+ }
+ if (!aflag && acct != NULL)
+ command ("ACCT %s", acct);
+ if (proxy)
+ return (1);
+ for (n = 0; n < macnum; ++n) {
+ if (!strcmp("init", macros[n].mac_name)) {
+ strlcpy (line, "$init", sizeof (line));
+ makeargv();
+ domacro(margc, margv);
+ break;
+ }
+ }
+ sec_set_protection_level ();
+ return (1);
+}
+
+void
+cmdabort (int sig)
+{
+
+ printf ("\n");
+ fflush (stdout);
+ abrtflag++;
+ if (ptflag)
+ longjmp (ptabort, 1);
+}
+
+int
+command (char *fmt,...)
+{
+ va_list ap;
+ int r;
+ sighand oldintr;
+
+ abrtflag = 0;
+ if (cout == NULL) {
+ warn ("No control connection for command");
+ code = -1;
+ return (0);
+ }
+ oldintr = signal(SIGINT, cmdabort);
+ va_start(ap, fmt);
+ if(debug){
+ printf("---> ");
+ if (strncmp("PASS ", fmt, 5) == 0)
+ printf("PASS XXXX");
+ else
+ vfprintf(stdout, fmt, ap);
+ va_start(ap, fmt);
+ }
+ sec_vfprintf(cout, fmt, ap);
+ va_end(ap);
+ if(debug){
+ printf("\n");
+ fflush(stdout);
+ }
+ fprintf (cout, "\r\n");
+ fflush (cout);
+ cpend = 1;
+ r = getreply (!strcmp (fmt, "QUIT"));
+ if (abrtflag && oldintr != SIG_IGN)
+ (*oldintr) (SIGINT);
+ signal (SIGINT, oldintr);
+ return (r);
+}
+
+char reply_string[BUFSIZ]; /* last line of previous reply */
+
+int
+getreply (int expecteof)
+{
+ char *p;
+ char *lead_string;
+ int c;
+ struct sigaction sa, osa;
+ char buf[1024];
+
+ sigemptyset (&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = cmdabort;
+ sigaction (SIGINT, &sa, &osa);
+
+ p = buf;
+
+ while (1) {
+ c = getc (cin);
+ switch (c) {
+ case EOF:
+ if (expecteof) {
+ sigaction (SIGINT, &osa, NULL);
+ code = 221;
+ return 0;
+ }
+ lostpeer (0);
+ if (verbose) {
+ printf ("421 Service not available, "
+ "remote server has closed connection\n");
+ fflush (stdout);
+ }
+ code = 421;
+ return (4);
+ case IAC:
+ c = getc (cin);
+ if (c == WILL || c == WONT)
+ fprintf (cout, "%c%c%c", IAC, DONT, getc (cin));
+ if (c == DO || c == DONT)
+ fprintf (cout, "%c%c%c", IAC, WONT, getc (cin));
+ continue;
+ case '\n':
+ *p++ = '\0';
+ if(isdigit(buf[0])){
+ sscanf(buf, "%d", &code);
+ if(code == 631){
+ sec_read_msg(buf, prot_safe);
+ sscanf(buf, "%d", &code);
+ lead_string = "S:";
+ } else if(code == 632){
+ sec_read_msg(buf, prot_private);
+ sscanf(buf, "%d", &code);
+ lead_string = "P:";
+ }else if(code == 633){
+ sec_read_msg(buf, prot_confidential);
+ sscanf(buf, "%d", &code);
+ lead_string = "C:";
+ }else if(sec_complete)
+ lead_string = "!!";
+ else
+ lead_string = "";
+ if (verbose > 0 || (verbose > -1 && code > 499))
+ fprintf (stdout, "%s%s\n", lead_string, buf);
+ if (buf[3] == ' ') {
+ strcpy (reply_string, buf);
+ if (code >= 200)
+ cpend = 0;
+ sigaction (SIGINT, &osa, NULL);
+ if (code == 421)
+ lostpeer (0);
+#if 1
+ if (abrtflag &&
+ osa.sa_handler != cmdabort &&
+ osa.sa_handler != SIG_IGN)
+ osa.sa_handler (SIGINT);
+#endif
+ if (code == 227 || code == 229) {
+ char *p, *q;
+
+ pasv[0] = 0;
+ p = strchr (reply_string, '(');
+ if (p) {
+ p++;
+ q = strchr(p, ')');
+ if(q){
+ memcpy (pasv, p, q - p);
+ pasv[q - p] = 0;
+ }
+ }
+ }
+ return code / 100;
+ }
+ }else{
+ if(verbose > 0 || (verbose > -1 && code > 499)){
+ if(sec_complete)
+ fprintf(stdout, "!!");
+ fprintf(stdout, "%s\n", buf);
+ }
+ }
+ p = buf;
+ continue;
+ default:
+ *p++ = c;
+ }
+ }
+
+}
+
+
+#if 0
+int
+getreply (int expecteof)
+{
+ int c, n;
+ int dig;
+ int originalcode = 0, continuation = 0;
+ sighand oldintr;
+ int pflag = 0;
+ char *cp, *pt = 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);
+ fflush (cout);
+ break;
+ case DO:
+ case DONT:
+ c = getc (cin);
+ fprintf (cout, "%c%c%c", IAC, WONT, c);
+ fflush (cout);
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ dig++;
+ if (c == EOF) {
+ if (expecteof) {
+ signal (SIGINT, oldintr);
+ code = 221;
+ return (0);
+ }
+ lostpeer (0);
+ if (verbose) {
+ printf ("421 Service not available, remote server has closed connection\n");
+ 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);
+ putchar (c);
+ }
+ if (dig < 4 && isdigit (c))
+ code = code * 10 + (c - '0');
+ if (!pflag && code == 227)
+ pflag = 1;
+ if (dig > 4 && pflag == 1 && isdigit (c))
+ pflag = 2;
+ if (pflag == 2) {
+ if (c != '\r' && c != ')')
+ *pt++ = c;
+ else {
+ *pt = '\0';
+ pflag = 3;
+ }
+ }
+ 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') {
+ putchar (c);
+ fflush (stdout);
+ }
+ if (continuation && code != originalcode) {
+ if (originalcode == 0)
+ originalcode = code;
+ continue;
+ }
+ *cp = '\0';
+ if(sec_complete){
+ if(code == 631)
+ sec_read_msg(reply_string, prot_safe);
+ else if(code == 632)
+ sec_read_msg(reply_string, prot_private);
+ else if(code == 633)
+ sec_read_msg(reply_string, prot_confidential);
+ n = code / 100 + '0';
+ }
+ if (n != '1')
+ cpend = 0;
+ signal (SIGINT, oldintr);
+ if (code == 421 || originalcode == 421)
+ lostpeer (0);
+ if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
+ (*oldintr) (SIGINT);
+ return (n - '0');
+ }
+}
+
+#endif
+
+int
+empty (fd_set * mask, int sec)
+{
+ struct timeval t;
+
+ t.tv_sec = (long) sec;
+ t.tv_usec = 0;
+ return (select (32, mask, NULL, NULL, &t));
+}
+
+jmp_buf sendabort;
+
+static RETSIGTYPE
+abortsend (int sig)
+{
+
+ mflag = 0;
+ abrtflag = 0;
+ printf ("\nsend aborted\nwaiting for remote to finish abort\n");
+ fflush (stdout);
+ longjmp (sendabort, 1);
+}
+
+#define HASHBYTES 1024
+
+static int
+copy_stream (FILE * from, FILE * to)
+{
+ static size_t bufsize;
+ static char *buf;
+ int n;
+ int bytes = 0;
+ int werr = 0;
+ int hashbytes = HASHBYTES;
+ struct stat st;
+
+#if defined(HAVE_MMAP) && !defined(NO_MMAP)
+ void *chunk;
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+
+ if (fstat (fileno (from), &st) == 0 && S_ISREG (st.st_mode)) {
+ /*
+ * mmap zero bytes has potential of loosing, don't do it.
+ */
+ if (st.st_size == 0)
+ return 0;
+ chunk = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fileno (from), 0);
+ if (chunk != (void *) MAP_FAILED) {
+ int res;
+
+ res = sec_write (fileno (to), chunk, st.st_size);
+ if (munmap (chunk, st.st_size) < 0)
+ warn ("munmap");
+ sec_fflush (to);
+ return res;
+ }
+ }
+#endif
+
+ buf = alloc_buffer (buf, &bufsize,
+ fstat (fileno (from), &st) >= 0 ? &st : NULL);
+ if (buf == NULL)
+ return -1;
+
+ while ((n = read (fileno (from), buf, bufsize)) > 0) {
+ werr = sec_write (fileno (to), buf, n);
+ if (werr < 0)
+ break;
+ bytes += werr;
+ while (hash && bytes > hashbytes) {
+ putchar ('#');
+ hashbytes += HASHBYTES;
+ }
+ }
+ sec_fflush (to);
+ if (n < 0)
+ warn ("local");
+
+ if (werr < 0) {
+ if (errno != EPIPE)
+ warn ("netout");
+ bytes = -1;
+ }
+ return bytes;
+}
+
+void
+sendrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
+{
+ struct stat st;
+ struct timeval start, stop;
+ int c, d;
+ FILE *fin, *dout = 0;
+ int (*closefunc) (FILE *);
+ RETSIGTYPE (*oldintr)(), (*oldintp)();
+ long bytes = 0, hashbytes = HASHBYTES;
+ char *rmode = "w";
+
+ if (verbose && printnames) {
+ if (local && strcmp (local, "-") != 0)
+ 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;
+
+ if (setjmp (sendabort)) {
+ while (cpend) {
+ getreply (0);
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (oldintr)
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ 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, lmode);
+ if (fin == NULL) {
+ warn ("%s", local + 1);
+ signal (SIGINT, oldintr);
+ signal (SIGPIPE, oldintp);
+ code = -1;
+ return;
+ }
+ closefunc = pclose;
+ } else {
+ fin = fopen (local, lmode);
+ if (fin == NULL) {
+ warn ("local: %s", local);
+ 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);
+ signal (SIGINT, oldintr);
+ fclose (fin);
+ code = -1;
+ return;
+ }
+ }
+ if (initconn ()) {
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ code = -1;
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ if (setjmp (sendabort))
+ goto abort;
+
+ if (restart_point &&
+ (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0)) {
+ int rc;
+
+ switch (curtype) {
+ case TYPE_A:
+ rc = fseek (fin, (long) restart_point, SEEK_SET);
+ break;
+ case TYPE_I:
+ case TYPE_L:
+ rc = lseek (fileno (fin), restart_point, SEEK_SET);
+ break;
+ }
+ if (rc < 0) {
+ warn ("local: %s", local);
+ 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;
+ rmode = "r+w";
+ }
+ if (remote) {
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ return;
+ }
+ } else if (command ("%s", cmd) != PRELIM) {
+ signal(SIGINT, oldintr);
+ if (oldintp)
+ signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
+ return;
+ }
+ dout = dataconn(rmode);
+ if (dout == NULL)
+ goto abort;
+ set_buffer_size (fileno (dout), 0);
+ gettimeofday (&start, (struct timezone *) 0);
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ switch (curtype) {
+
+ case TYPE_I:
+ case TYPE_L:
+ errno = d = c = 0;
+ bytes = copy_stream (fin, dout);
+ break;
+
+ case TYPE_A:
+ while ((c = getc (fin)) != EOF) {
+ if (c == '\n') {
+ while (hash && (bytes >= hashbytes)) {
+ putchar ('#');
+ fflush (stdout);
+ hashbytes += HASHBYTES;
+ }
+ if (ferror (dout))
+ break;
+ sec_putc ('\r', dout);
+ bytes++;
+ }
+ sec_putc (c, dout);
+ bytes++;
+ }
+ sec_fflush (dout);
+ if (hash) {
+ if (bytes < hashbytes)
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
+ }
+ if (ferror (fin))
+ warn ("local: %s", local);
+ if (ferror (dout)) {
+ if (errno != EPIPE)
+ warn ("netout");
+ bytes = -1;
+ }
+ break;
+ }
+ if (closefunc != NULL)
+ (*closefunc) (fin);
+ fclose (dout);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (bytes > 0)
+ ptransfer ("sent", bytes, &start, &stop);
+ return;
+abort:
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ if (!cpend) {
+ code = -1;
+ return;
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (dout)
+ fclose (dout);
+ getreply (0);
+ code = -1;
+ if (closefunc != NULL && fin != NULL)
+ (*closefunc) (fin);
+ gettimeofday (&stop, (struct timezone *) 0);
+ if (bytes > 0)
+ ptransfer ("sent", bytes, &start, &stop);
+}
+
+jmp_buf recvabort;
+
+void
+abortrecv (int sig)
+{
+
+ mflag = 0;
+ abrtflag = 0;
+ printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
+ fflush (stdout);
+ longjmp (recvabort, 1);
+}
+
+void
+recvrequest (char *cmd, char *local, char *remote,
+ char *lmode, int printnames, int local_given)
+{
+ FILE *fout, *din = 0;
+ int (*closefunc) (FILE *);
+ sighand oldintr, oldintp;
+ int c, d, is_retr, tcrflag, bare_lfs = 0;
+ static size_t bufsize;
+ static char *buf;
+ long bytes = 0, hashbytes = HASHBYTES;
+ struct timeval start, stop;
+ struct stat st;
+
+ is_retr = strcmp (cmd, "RETR") == 0;
+ if (is_retr && verbose && printnames) {
+ if (local && strcmp (local, "-") != 0)
+ 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 (setjmp (recvabort)) {
+ while (cpend) {
+ getreply (0);
+ }
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (oldintr)
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ oldintr = signal (SIGINT, abortrecv);
+ if (!local_given || (strcmp (local, "-") && *local != '|')) {
+ if (access (local, 2) < 0) {
+ char *dir = strrchr (local, '/');
+
+ if (errno != ENOENT && errno != EACCES) {
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (dir != NULL)
+ *dir = 0;
+ d = access (dir ? local : ".", 2);
+ if (dir != NULL)
+ *dir = '/';
+ if (d < 0) {
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (!runique && errno == EACCES &&
+ chmod (local, 0600) < 0) {
+ warn ("local: %s", local);
+ signal (SIGINT, oldintr);
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (runique && errno == EACCES &&
+ (local = gunique (local)) == NULL) {
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ } else if (runique && (local = gunique (local)) == NULL) {
+ 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 ()) {
+ signal (SIGINT, oldintr);
+ code = -1;
+ return;
+ }
+ if (setjmp (recvabort))
+ goto abort;
+ if (is_retr && restart_point &&
+ command ("REST %ld", (long) restart_point) != CONTINUE)
+ return;
+ if (remote) {
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ return;
+ }
+ } else {
+ if (command ("%s", cmd) != PRELIM) {
+ signal (SIGINT, oldintr);
+ return;
+ }
+ }
+ din = dataconn ("r");
+ if (din == NULL)
+ goto abort;
+ set_buffer_size (fileno (din), 1);
+ if (local_given && strcmp (local, "-") == 0)
+ fout = stdout;
+ else if (local_given && *local == '|') {
+ oldintp = signal (SIGPIPE, SIG_IGN);
+ fout = popen (local + 1, "w");
+ if (fout == NULL) {
+ warn ("%s", local + 1);
+ goto abort;
+ }
+ closefunc = pclose;
+ } else {
+ fout = fopen (local, lmode);
+ if (fout == NULL) {
+ warn ("local: %s", local);
+ goto abort;
+ }
+ closefunc = fclose;
+ }
+ buf = alloc_buffer (buf, &bufsize,
+ fstat (fileno (fout), &st) >= 0 ? &st : NULL);
+ if (buf == NULL)
+ goto abort;
+
+ gettimeofday (&start, (struct timezone *) 0);
+ switch (curtype) {
+
+ case TYPE_I:
+ case TYPE_L:
+ if (restart_point &&
+ lseek (fileno (fout), restart_point, SEEK_SET) < 0) {
+ warn ("local: %s", local);
+ if (closefunc != NULL)
+ (*closefunc) (fout);
+ return;
+ }
+ errno = d = 0;
+ while ((c = sec_read (fileno (din), buf, bufsize)) > 0) {
+ if ((d = write (fileno (fout), buf, c)) != c)
+ break;
+ bytes += c;
+ if (hash) {
+ while (bytes >= hashbytes) {
+ putchar ('#');
+ hashbytes += HASHBYTES;
+ }
+ fflush (stdout);
+ }
+ }
+ if (hash && bytes > 0) {
+ if (bytes < HASHBYTES)
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
+ }
+ if (c < 0) {
+ if (errno != EPIPE)
+ warn ("netin");
+ bytes = -1;
+ }
+ if (d < c) {
+ if (d < 0)
+ warn ("local: %s", local);
+ else
+ warnx ("%s: short write", local);
+ }
+ break;
+
+ case TYPE_A:
+ if (restart_point) {
+ int i, n, ch;
+
+ if (fseek (fout, 0L, SEEK_SET) < 0)
+ goto done;
+ n = restart_point;
+ for (i = 0; i++ < n;) {
+ if ((ch = sec_getc (fout)) == EOF)
+ goto done;
+ if (ch == '\n')
+ i++;
+ }
+ if (fseek (fout, 0L, SEEK_CUR) < 0) {
+ done:
+ warn ("local: %s", local);
+ if (closefunc != NULL)
+ (*closefunc) (fout);
+ return;
+ }
+ }
+ while ((c = sec_getc(din)) != EOF) {
+ if (c == '\n')
+ bare_lfs++;
+ while (c == '\r') {
+ while (hash && (bytes >= hashbytes)) {
+ putchar ('#');
+ fflush (stdout);
+ hashbytes += HASHBYTES;
+ }
+ bytes++;
+ if ((c = sec_getc (din)) != '\n' || tcrflag) {
+ if (ferror (fout))
+ goto break2;
+ putc ('\r', fout);
+ if (c == '\0') {
+ bytes++;
+ goto contin2;
+ }
+ if (c == EOF)
+ goto contin2;
+ }
+ }
+ putc (c, fout);
+ bytes++;
+ contin2:;
+ }
+break2:
+ if (bare_lfs) {
+ printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
+ bare_lfs);
+ printf ("File may not have transferred correctly.\n");
+ }
+ if (hash) {
+ if (bytes < hashbytes)
+ putchar ('#');
+ putchar ('\n');
+ fflush (stdout);
+ }
+ if (ferror (din)) {
+ if (errno != EPIPE)
+ warn ("netin");
+ bytes = -1;
+ }
+ if (ferror (fout))
+ warn ("local: %s", local);
+ break;
+ }
+ if (closefunc != NULL)
+ (*closefunc) (fout);
+ signal (SIGINT, oldintr);
+ if (oldintp)
+ signal (SIGPIPE, oldintp);
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
+ getreply (0);
+ if (bytes > 0 && is_retr)
+ ptransfer ("received", bytes, &start, &stop);
+ return;
+abort:
+
+ /* abort using RFC959 recommended IP,SYNC sequence */
+
+ if (oldintp)
+ signal (SIGPIPE, oldintr);
+ signal (SIGINT, SIG_IGN);
+ if (!cpend) {
+ code = -1;
+ signal (SIGINT, oldintr);
+ return;
+ }
+ abort_remote(din);
+ code = -1;
+ if (data >= 0) {
+ close (data);
+ data = -1;
+ }
+ if (closefunc != NULL && fout != NULL)
+ (*closefunc) (fout);
+ if (din)
+ fclose (din);
+ gettimeofday (&stop, (struct timezone *) 0);
+ if (bytes > 0)
+ ptransfer ("received", bytes, &start, &stop);
+ signal (SIGINT, oldintr);
+}
+
+static int
+parse_epsv (const char *str)
+{
+ char sep;
+ char *end;
+ int port;
+
+ if (*str == '\0')
+ return -1;
+ sep = *str++;
+ if (sep != *str++)
+ return -1;
+ if (sep != *str++)
+ return -1;
+ port = strtol (str, &end, 0);
+ if (str == end)
+ return -1;
+ if (end[0] != sep || end[1] != '\0')
+ return -1;
+ return htons(port);
+}
+
+static int
+parse_pasv (struct sockaddr_in *sin, const char *str)
+{
+ int a0, a1, a2, a3, p0, p1;
+
+ /*
+ * What we've got at this point is a string of comma separated
+ * one-byte unsigned integer values. The first four are the an IP
+ * address. The fifth is the MSB of the port number, the sixth is the
+ * LSB. From that we'll prepare a sockaddr_in.
+ */
+
+ if (sscanf (str, "%d,%d,%d,%d,%d,%d",
+ &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
+ printf ("Passive mode address scan failure. "
+ "Shouldn't happen!\n");
+ return -1;
+ }
+ if (a0 < 0 || a0 > 255 ||
+ a1 < 0 || a1 > 255 ||
+ a2 < 0 || a2 > 255 ||
+ a3 < 0 || a3 > 255 ||
+ p0 < 0 || p0 > 255 ||
+ p1 < 0 || p1 > 255) {
+ printf ("Can't parse passive mode string.\n");
+ return -1;
+ }
+ memset (sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl ((a0 << 24) | (a1 << 16) |
+ (a2 << 8) | a3);
+ sin->sin_port = htons ((p0 << 8) | p1);
+ return 0;
+}
+
+static int
+passive_mode (void)
+{
+ int port;
+
+ data = socket (myctladdr->sa_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ warn ("socket");
+ return (1);
+ }
+ if (options & SO_DEBUG)
+ socket_set_debug (data);
+ if (command ("EPSV") != COMPLETE) {
+ if (command ("PASV") != COMPLETE) {
+ printf ("Passive mode refused.\n");
+ goto bad;
+ }
+ }
+
+ /*
+ * Parse the reply to EPSV or PASV
+ */
+
+ port = parse_epsv (pasv);
+ if (port > 0) {
+ data_addr->sa_family = myctladdr->sa_family;
+ socket_set_address_and_port (data_addr,
+ socket_get_address (hisctladdr),
+ port);
+ } else {
+ if (parse_pasv ((struct sockaddr_in *)data_addr, pasv) < 0)
+ goto bad;
+ }
+
+ if (connect (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
+ warn ("connect");
+ goto bad;
+ }
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (data, IPTOS_THROUGHPUT);
+#endif
+ return (0);
+bad:
+ close (data);
+ data = -1;
+ sendport = 1;
+ return (1);
+}
+
+
+static int
+active_mode (void)
+{
+ int tmpno = 0;
+ int len;
+ int result;
+
+noport:
+ data_addr->sa_family = myctladdr->sa_family;
+ socket_set_address_and_port (data_addr, socket_get_address (myctladdr),
+ sendport ? 0 : socket_get_port (myctladdr));
+
+ if (data != -1)
+ close (data);
+ data = socket (data_addr->sa_family, SOCK_STREAM, 0);
+ if (data < 0) {
+ warn ("socket");
+ if (tmpno)
+ sendport = 1;
+ return (1);
+ }
+ if (!sendport)
+ socket_set_reuseaddr (data, 1);
+ if (bind (data, data_addr, socket_sockaddr_size (data_addr)) < 0) {
+ warn ("bind");
+ goto bad;
+ }
+ if (options & SO_DEBUG)
+ socket_set_debug (data);
+ len = sizeof (data_addr_ss);
+ if (getsockname (data, data_addr, &len) < 0) {
+ warn ("getsockname");
+ goto bad;
+ }
+ if (listen (data, 1) < 0)
+ warn ("listen");
+ if (sendport) {
+ char *cmd;
+ char addr_str[256];
+ int inet_af;
+ int overbose;
+
+ if (inet_ntop (data_addr->sa_family, socket_get_address (data_addr),
+ addr_str, sizeof(addr_str)) == NULL)
+ errx (1, "inet_ntop failed");
+ switch (data_addr->sa_family) {
+ case AF_INET :
+ inet_af = 1;
+ break;
+#ifdef HAVE_IPV6
+ case AF_INET6 :
+ inet_af = 2;
+ break;
+#endif
+ default :
+ errx (1, "bad address family %d", data_addr->sa_family);
+ }
+
+ asprintf (&cmd, "EPRT |%d|%s|%d|",
+ inet_af, addr_str, ntohs(socket_get_port (data_addr)));
+
+ overbose = verbose;
+ if (debug == 0)
+ verbose = -1;
+
+ result = command (cmd);
+
+ verbose = overbose;
+
+ if (result == ERROR) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)data_addr;
+
+ unsigned int a = ntohl(sin->sin_addr.s_addr);
+ unsigned int p = ntohs(sin->sin_port);
+
+ if (data_addr->sa_family != AF_INET) {
+ warnx ("remote server doesn't support EPRT");
+ goto bad;
+ }
+
+ result = command("PORT %d,%d,%d,%d,%d,%d",
+ (a >> 24) & 0xff,
+ (a >> 16) & 0xff,
+ (a >> 8) & 0xff,
+ a & 0xff,
+ (p >> 8) & 0xff,
+ p & 0xff);
+ if (result == ERROR && sendport == -1) {
+ sendport = 0;
+ tmpno = 1;
+ goto noport;
+ }
+ return (result != COMPLETE);
+ }
+ return result != COMPLETE;
+ }
+ if (tmpno)
+ sendport = 1;
+
+
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (data, IPTOS_THROUGHPUT);
+#endif
+ return (0);
+bad:
+ close (data);
+ data = -1;
+ if (tmpno)
+ sendport = 1;
+ return (1);
+}
+
+/*
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
+ */
+int
+initconn (void)
+{
+ if (passivemode)
+ return passive_mode ();
+ else
+ return active_mode ();
+}
+
+FILE *
+dataconn (const char *lmode)
+{
+ struct sockaddr_storage from_ss;
+ struct sockaddr *from = (struct sockaddr *)&from_ss;
+ int s, fromlen = sizeof (from_ss);
+
+ if (passivemode)
+ return (fdopen (data, lmode));
+
+ s = accept (data, from, &fromlen);
+ if (s < 0) {
+ warn ("accept");
+ close (data), data = -1;
+ return (NULL);
+ }
+ close (data);
+ data = s;
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (s, IPTOS_THROUGHPUT);
+#endif
+ return (fdopen (data, lmode));
+}
+
+void
+ptransfer (char *direction, long int bytes,
+ struct timeval * t0, struct timeval * t1)
+{
+ struct timeval td;
+ float s;
+ float bs;
+ int prec;
+ char *unit;
+
+ if (verbose) {
+ td.tv_sec = t1->tv_sec - t0->tv_sec;
+ td.tv_usec = t1->tv_usec - t0->tv_usec;
+ if (td.tv_usec < 0) {
+ td.tv_sec--;
+ td.tv_usec += 1000000;
+ }
+ s = td.tv_sec + (td.tv_usec / 1000000.);
+ bs = bytes / (s ? s : 1);
+ if (bs >= 1048576) {
+ bs /= 1048576;
+ unit = "M";
+ prec = 2;
+ } else if (bs >= 1024) {
+ bs /= 1024;
+ unit = "k";
+ prec = 1;
+ } else {
+ unit = "";
+ prec = 0;
+ }
+
+ printf ("%ld bytes %s in %.3g seconds (%.*f %sbyte/s)\n",
+ bytes, direction, s, prec, bs, unit);
+ }
+}
+
+void
+psabort (int sig)
+{
+
+ abrtflag++;
+}
+
+void
+pswitch (int flag)
+{
+ sighand oldintr;
+ static struct comvars {
+ int connect;
+ char name[MaxHostNameLen];
+ struct sockaddr_storage mctl;
+ struct sockaddr_storage hctl;
+ FILE *in;
+ FILE *out;
+ int tpe;
+ int curtpe;
+ int cpnd;
+ int sunqe;
+ int runqe;
+ int mcse;
+ int ntflg;
+ char nti[17];
+ char nto[17];
+ 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) {
+ strlcpy (ip->name, hostname, sizeof (ip->name));
+ } else
+ ip->name[0] = 0;
+ hostname = op->name;
+ ip->hctl = hisctladdr_ss;
+ hisctladdr_ss = op->hctl;
+ ip->mctl = myctladdr_ss;
+ myctladdr_ss = 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;
+ strlcpy (ip->nti, ntin, sizeof (ip->nti));
+ strlcpy (ntin, op->nti, 17);
+ strlcpy (ip->nto, ntout, sizeof (ip->nto));
+ strlcpy (ntout, op->nto, 17);
+ ip->mapflg = mapflag;
+ mapflag = op->mapflg;
+ strlcpy (ip->mi, mapin, MaxPathLen);
+ strlcpy (mapin, op->mi, MaxPathLen);
+ strlcpy (ip->mo, mapout, MaxPathLen);
+ strlcpy (mapout, op->mo, MaxPathLen);
+ signal(SIGINT, oldintr);
+ if (abrtflag) {
+ abrtflag = 0;
+ (*oldintr) (SIGINT);
+ }
+}
+
+void
+abortpt (int sig)
+{
+
+ printf ("\n");
+ fflush (stdout);
+ ptabflg++;
+ mflag = 0;
+ abrtflag = 0;
+ longjmp (ptabort, 1);
+}
+
+void
+proxtrans (char *cmd, char *local, char *remote)
+{
+ sighand oldintr;
+ int secndflag = 0, prox_type, nfnd;
+ char *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 (setjmp (ptabort))
+ goto abort;
+ oldintr = signal (SIGINT, abortpt);
+ if (command ("%s %s", cmd, remote) != PRELIM) {
+ signal (SIGINT, oldintr);
+ pswitch (1);
+ return;
+ }
+ sleep (2);
+ pswitch (1);
+ secndflag++;
+ if (command ("%s %s", cmd2, local) != PRELIM)
+ goto abort;
+ ptflag++;
+ getreply (0);
+ pswitch (0);
+ getreply (0);
+ signal (SIGINT, oldintr);
+ pswitch (1);
+ ptflag = 0;
+ printf ("local: %s remote: %s\n", local, remote);
+ return;
+abort:
+ 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;
+ 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;
+ 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, 10)) <= 0) {
+ if (nfnd < 0) {
+ warn ("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer (0);
+ }
+ getreply (0);
+ getreply (0);
+ }
+ if (proxy)
+ pswitch (0);
+ pswitch (1);
+ if (ptabflg)
+ code = -1;
+ signal (SIGINT, oldintr);
+}
+
+void
+reset (int argc, char **argv)
+{
+ fd_set mask;
+ int nfnd = 1;
+
+ FD_ZERO (&mask);
+ while (nfnd > 0) {
+ FD_SET (fileno (cin), &mask);
+ if ((nfnd = empty (&mask, 0)) < 0) {
+ warn ("reset");
+ code = -1;
+ lostpeer(0);
+ } else if (nfnd) {
+ getreply(0);
+ }
+ }
+}
+
+char *
+gunique (char *local)
+{
+ static char new[MaxPathLen];
+ char *cp = strrchr (local, '/');
+ int d, count = 0;
+ char ext = '1';
+
+ if (cp)
+ *cp = '\0';
+ d = access (cp ? local : ".", 2);
+ if (cp)
+ *cp = '/';
+ if (d < 0) {
+ warn ("local: %s", local);
+ return NULL;
+ }
+ strlcpy (new, local, sizeof(new));
+ cp = new + strlen(new);
+ *cp++ = '.';
+ while (!d) {
+ if (++count == 100) {
+ printf ("runique: can't find unique file name.\n");
+ return NULL;
+ }
+ *cp++ = ext;
+ *cp = '\0';
+ if (ext == '9')
+ ext = '0';
+ else
+ ext++;
+ if ((d = access (new, 0)) < 0)
+ break;
+ if (ext != '0')
+ cp--;
+ else if (*(cp - 2) == '.')
+ *(cp - 1) = '1';
+ else {
+ *(cp - 2) = *(cp - 2) + 1;
+ cp--;
+ }
+ }
+ return (new);
+}
+
+void
+abort_remote (FILE * din)
+{
+ char buf[BUFSIZ];
+ int nfnd;
+ 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)
+ warn ("abort");
+ fprintf (cout, "%cABOR\r\n", DM);
+ fflush (cout);
+ FD_ZERO (&mask);
+ FD_SET (fileno (cin), &mask);
+ if (din) {
+ FD_SET (fileno (din), &mask);
+ }
+ if ((nfnd = empty (&mask, 10)) <= 0) {
+ if (nfnd < 0) {
+ warn ("abort");
+ }
+ if (ptabflg)
+ code = -1;
+ lostpeer (0);
+ }
+ 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 */
+ getreply (0);
+ }
+ getreply (0);
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/ftp_locl.h b/crypto/heimdal/appl/ftp/ftp/ftp_locl.h
new file mode 100644
index 0000000..49c2b2f
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/ftp_locl.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: ftp_locl.h,v 1.34 1999/12/02 16:58:29 joda Exp $ */
+
+#ifndef __FTP_LOCL_H__
+#define __FTP_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_ARPA_FTP_H
+#include <arpa/ftp.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#include <errno.h>
+#include <ctype.h>
+#include <glob.h>
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <err.h>
+
+#ifdef SOCKS
+#include <socks.h>
+extern int LIBPREFIX(fclose) (FILE *);
+
+/* This doesn't belong here. */
+struct tm *localtime(const time_t *);
+struct hostent *gethostbyname(const char *);
+
+#endif
+
+#include "ftp_var.h"
+#include "extern.h"
+#include "common.h"
+#include "pathnames.h"
+
+#include "roken.h"
+#include "security.h"
+#include <des.h> /* for des_read_pw_string */
+
+#if defined(__sun__) && !defined(__svr4)
+int fclose(FILE*);
+int pclose(FILE*);
+#endif
+
+#endif /* __FTP_LOCL_H__ */
diff --git a/crypto/heimdal/appl/ftp/ftp/ftp_var.h b/crypto/heimdal/appl/ftp/ftp/ftp_var.h
new file mode 100644
index 0000000..ffac59a
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/ftp_var.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ *
+ * @(#)ftp_var.h 8.4 (Berkeley) 10/9/94
+ */
+
+/*
+ * FTP global variables.
+ */
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <setjmp.h>
+
+/*
+ * Options and other state info.
+ */
+extern int trace; /* trace packets exchanged */
+extern int hash; /* print # for each buffer transferred */
+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 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 translation */
+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[17]; /* input translation table */
+extern char ntout[17]; /* 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 jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
+
+extern char line[200]; /* input line buffer */
+extern char *stringbase; /* current scan point in line buffer */
+extern char argbuf[200]; /* argument storage buffer */
+extern char *argbase; /* current storage point in arg buffer */
+extern int margc; /* count of arguments on input line */
+extern char **margv; /* args parsed from input line */
+extern int margvlen; /* how large margv is currently */
+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 */
+
+/*
+ * Format of command table.
+ */
+struct cmd {
+ char *c_name; /* name of command */
+ 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 */
+ void (*c_handler) (int, char **); /* function to call */
+};
+
+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];
+
+
diff --git a/crypto/heimdal/appl/ftp/ftp/globals.c b/crypto/heimdal/appl/ftp/ftp/globals.c
new file mode 100644
index 0000000..7199e65
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/globals.c
@@ -0,0 +1,76 @@
+#include "ftp_locl.h"
+RCSID("$Id: globals.c,v 1.6 1996/08/26 22:46:26 assar Exp $");
+
+/*
+ * Options and other state info.
+ */
+int trace; /* trace packets exchanged */
+int hash; /* print # for each buffer transferred */
+int sendport; /* use PORT cmd for each data connection */
+int verbose; /* print messages coming back from server */
+int connected; /* connected to server */
+int fromatty; /* input is from a terminal */
+int interactive; /* interactively prompt on m* cmds */
+int debug; /* debugging level */
+int bell; /* ring bell on cmd completion */
+int doglob; /* glob local file names */
+int autologin; /* establish user account on connection */
+int proxy; /* proxy server connection active */
+int proxflag; /* proxy connection exists */
+int sunique; /* store files on server with unique name */
+int runique; /* store local files with unique name */
+int mcase; /* map upper to lower case for mget names */
+int ntflag; /* use ntin ntout tables for name translation */
+int mapflag; /* use mapin mapout templates on file names */
+int code; /* return/reply code for ftp command */
+int crflag; /* if 1, strip car. rets. on ascii gets */
+char pasv[64]; /* passive port for proxy data connection */
+int passivemode; /* passive mode enabled */
+char *altarg; /* argv[1] with no shell-like preprocessing */
+char ntin[17]; /* input translation table */
+char ntout[17]; /* output translation table */
+char mapin[MaxPathLen]; /* input map template */
+char mapout[MaxPathLen]; /* output map template */
+char typename[32]; /* name of file transfer type */
+int type; /* requested file transfer type */
+int curtype; /* current file transfer type */
+char structname[32]; /* name of file transfer structure */
+int stru; /* file transfer structure */
+char formname[32]; /* name of file transfer format */
+int form; /* file transfer format */
+char modename[32]; /* name of file transfer mode */
+int mode; /* file transfer mode */
+char bytename[32]; /* local byte size in ascii */
+int bytesize; /* local byte size in binary */
+
+char *hostname; /* name of host connected to */
+int unix_server; /* server is unix, can use binary for ascii */
+int unix_proxy; /* proxy is unix, can use binary for ascii */
+
+jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
+
+char line[200]; /* input line buffer */
+char *stringbase; /* current scan point in line buffer */
+char argbuf[200]; /* argument storage buffer */
+char *argbase; /* current storage point in arg buffer */
+int margc; /* count of arguments on input line */
+char **margv; /* args parsed from input line */
+int margvlen; /* how large margv is currently */
+int cpend; /* flag: if != 0, then pending server reply */
+int mflag; /* flag: if != 0, then active multi command */
+
+int options; /* used during socket creation */
+
+/*
+ * Format of command table.
+ */
+
+int macnum; /* number of defined macros */
+struct macel macros[16];
+char macbuf[4096];
+
+char username[32];
+
+/* these are set in ruserpass */
+char myhostname[MaxHostNameLen];
+char *mydomain;
diff --git a/crypto/heimdal/appl/ftp/ftp/gssapi.c b/crypto/heimdal/appl/ftp/ftp/gssapi.c
new file mode 100644
index 0000000..d06b5d6
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/gssapi.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
+#include "ftp_locl.h"
+#endif
+#include <gssapi.h>
+
+RCSID("$Id: gssapi.c,v 1.13 1999/12/02 16:58:29 joda Exp $");
+
+struct gss_data {
+ gss_ctx_id_t context_hdl;
+ char *client_name;
+};
+
+static int
+gss_init(void *app_data)
+{
+ struct gss_data *d = app_data;
+ d->context_hdl = GSS_C_NO_CONTEXT;
+ return 0;
+}
+
+static int
+gss_check_prot(void *app_data, int level)
+{
+ if(level == prot_confidential)
+ return -1;
+ return 0;
+}
+
+static int
+gss_decode(void *app_data, void *buf, int len, int level)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input, output;
+ gss_qop_t qop_state;
+ int conf_state;
+ struct gss_data *d = app_data;
+
+ input.length = len;
+ input.value = buf;
+ maj_stat = gss_unwrap (&min_stat,
+ d->context_hdl,
+ &input,
+ &output,
+ &conf_state,
+ &qop_state);
+ if(GSS_ERROR(maj_stat))
+ return -1;
+ memmove(buf, output.value, output.length);
+ return output.length;
+}
+
+static int
+gss_overhead(void *app_data, int level, int len)
+{
+ return 100; /* dunno? */
+}
+
+
+static int
+gss_encode(void *app_data, void *from, int length, int level, void **to)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc input, output;
+ int conf_state;
+ struct gss_data *d = app_data;
+
+ input.length = length;
+ input.value = from;
+ maj_stat = gss_wrap (&min_stat,
+ d->context_hdl,
+ level == prot_private,
+ GSS_C_QOP_DEFAULT,
+ &input,
+ &conf_state,
+ &output);
+ *to = output.value;
+ return output.length;
+}
+
+static void
+sockaddr_to_gss_address (const struct sockaddr *sa,
+ OM_uint32 *addr_type,
+ gss_buffer_desc *gss_addr)
+{
+ switch (sa->sa_family) {
+#ifdef HAVE_IPV6
+ case AF_INET6 : {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+ gss_addr->length = 16;
+ gss_addr->value = &sin6->sin6_addr;
+ *addr_type = GSS_C_AF_INET6;
+ break;
+ }
+#endif
+ case AF_INET : {
+ struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+ gss_addr->length = 4;
+ gss_addr->value = &sin->sin_addr;
+ *addr_type = GSS_C_AF_INET;
+ break;
+ }
+ default :
+ errx (1, "unknown address family %d", sa->sa_family);
+
+ }
+}
+
+/* end common stuff */
+
+#ifdef FTP_SERVER
+
+static int
+gss_adat(void *app_data, void *buf, size_t len)
+{
+ char *p = NULL;
+ gss_buffer_desc input_token, output_token;
+ OM_uint32 maj_stat, min_stat;
+ gss_name_t client_name;
+ struct gss_data *d = app_data;
+
+ gss_channel_bindings_t bindings = malloc(sizeof(*bindings));
+ sockaddr_to_gss_address (his_addr,
+ &bindings->initiator_addrtype,
+ &bindings->initiator_address);
+ sockaddr_to_gss_address (ctrl_addr,
+ &bindings->acceptor_addrtype,
+ &bindings->acceptor_address);
+
+ bindings->application_data.length = 0;
+ bindings->application_data.value = NULL;
+
+ input_token.value = buf;
+ input_token.length = len;
+
+ maj_stat = gss_accept_sec_context (&min_stat,
+ &d->context_hdl,
+ GSS_C_NO_CREDENTIAL,
+ &input_token,
+ bindings,
+ &client_name,
+ NULL,
+ &output_token,
+ NULL,
+ NULL,
+ NULL);
+
+ if(output_token.length) {
+ if(base64_encode(output_token.value, output_token.length, &p) < 0) {
+ reply(535, "Out of memory base64-encoding.");
+ return -1;
+ }
+ }
+ if(maj_stat == GSS_S_COMPLETE){
+ char *name;
+ gss_buffer_desc export_name;
+ maj_stat = gss_export_name(&min_stat, client_name, &export_name);
+ if(maj_stat != 0) {
+ reply(500, "Error exporting name");
+ goto out;
+ }
+ name = realloc(export_name.value, export_name.length + 1);
+ if(name == NULL) {
+ reply(500, "Out of memory");
+ free(export_name.value);
+ goto out;
+ }
+ name[export_name.length] = '\0';
+ d->client_name = name;
+ if(p)
+ reply(235, "ADAT=%s", p);
+ else
+ reply(235, "ADAT Complete");
+ sec_complete = 1;
+
+ } else if(maj_stat == GSS_S_CONTINUE_NEEDED) {
+ if(p)
+ reply(335, "ADAT=%s", p);
+ else
+ reply(335, "OK, need more data");
+ } else
+ reply(535, "foo?");
+out:
+ free(p);
+ return 0;
+}
+
+int gss_userok(void*, char*);
+
+struct sec_server_mech gss_server_mech = {
+ "GSSAPI",
+ sizeof(struct gss_data),
+ gss_init, /* init */
+ NULL, /* end */
+ gss_check_prot,
+ gss_overhead,
+ gss_encode,
+ gss_decode,
+ /* */
+ NULL,
+ gss_adat,
+ NULL, /* pbsz */
+ NULL, /* ccc */
+ gss_userok
+};
+
+#else /* FTP_SERVER */
+
+extern struct sockaddr *hisctladdr, *myctladdr;
+
+static int
+gss_auth(void *app_data, char *host)
+{
+
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc name;
+ gss_name_t target_name;
+ gss_buffer_desc input, output_token;
+ int context_established = 0;
+ char *p;
+ int n;
+ gss_channel_bindings_t bindings;
+ struct gss_data *d = app_data;
+
+ name.length = asprintf((char**)&name.value, "ftp@%s", host);
+ maj_stat = gss_import_name(&min_stat,
+ &name,
+ GSS_C_NT_HOSTBASED_SERVICE,
+ &target_name);
+ if (GSS_ERROR(maj_stat)) {
+ OM_uint32 new_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+
+ gss_display_status(&new_stat,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ printf("Error importing name %s: %s\n",
+ (char *)name.value,
+ (char *)status_string.value);
+ gss_release_buffer(&new_stat, &status_string);
+ return AUTH_ERROR;
+ }
+ free(name.value);
+
+
+ input.length = 0;
+ input.value = NULL;
+
+ bindings = malloc(sizeof(*bindings));
+
+ sockaddr_to_gss_address (myctladdr,
+ &bindings->initiator_addrtype,
+ &bindings->initiator_address);
+ sockaddr_to_gss_address (hisctladdr,
+ &bindings->acceptor_addrtype,
+ &bindings->acceptor_address);
+
+ bindings->application_data.length = 0;
+ bindings->application_data.value = NULL;
+
+ while(!context_established) {
+ maj_stat = gss_init_sec_context(&min_stat,
+ GSS_C_NO_CREDENTIAL,
+ &d->context_hdl,
+ target_name,
+ GSS_C_NO_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+ 0,
+ bindings,
+ &input,
+ NULL,
+ &output_token,
+ NULL,
+ NULL);
+ if (GSS_ERROR(maj_stat)) {
+ OM_uint32 new_stat;
+ OM_uint32 msg_ctx = 0;
+ gss_buffer_desc status_string;
+
+ gss_display_status(&new_stat,
+ min_stat,
+ GSS_C_MECH_CODE,
+ GSS_C_NO_OID,
+ &msg_ctx,
+ &status_string);
+ printf("Error initializing security context: %s\n",
+ (char*)status_string.value);
+ gss_release_buffer(&new_stat, &status_string);
+ return AUTH_CONTINUE;
+ }
+
+ gss_release_buffer(&min_stat, &input);
+ if (output_token.length != 0) {
+ base64_encode(output_token.value, output_token.length, &p);
+ gss_release_buffer(&min_stat, &output_token);
+ n = command("ADAT %s", p);
+ free(p);
+ }
+ if (GSS_ERROR(maj_stat)) {
+ if (d->context_hdl != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context (&min_stat,
+ &d->context_hdl,
+ GSS_C_NO_BUFFER);
+ break;
+ }
+ if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+ p = strstr(reply_string, "ADAT=");
+ if(p == NULL){
+ printf("Error: expected ADAT in reply.\n");
+ return AUTH_ERROR;
+ } else {
+ p+=5;
+ input.value = malloc(strlen(p));
+ input.length = base64_decode(p, input.value);
+ }
+ } else {
+ if(code != 235) {
+ printf("Unrecognized response code: %d\n", code);
+ return AUTH_ERROR;
+ }
+ context_established = 1;
+ }
+ }
+ return AUTH_OK;
+}
+
+struct sec_client_mech gss_client_mech = {
+ "GSSAPI",
+ sizeof(struct gss_data),
+ gss_init,
+ gss_auth,
+ NULL, /* end */
+ gss_check_prot,
+ gss_overhead,
+ gss_encode,
+ gss_decode,
+};
+
+#endif /* FTP_SERVER */
diff --git a/crypto/heimdal/appl/ftp/ftp/kauth.c b/crypto/heimdal/appl/ftp/ftp/kauth.c
new file mode 100644
index 0000000..613593a
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/kauth.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "ftp_locl.h"
+#include <krb.h>
+RCSID("$Id: kauth.c,v 1.20 1999/12/02 16:58:29 joda Exp $");
+
+void
+kauth(int argc, char **argv)
+{
+ int ret;
+ char buf[1024];
+ des_cblock key;
+ des_key_schedule schedule;
+ KTEXT_ST tkt, tktcopy;
+ char *name;
+ char *p;
+ int overbose;
+ char passwd[100];
+ int tmp;
+
+ int save;
+
+ if(argc > 2){
+ printf("usage: %s [principal]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if(argc == 2)
+ name = argv[1];
+ else
+ name = username;
+
+ overbose = verbose;
+ verbose = 0;
+
+ save = set_command_prot(prot_private);
+ ret = command("SITE KAUTH %s", name);
+ if(ret != CONTINUE){
+ verbose = overbose;
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ verbose = overbose;
+ p = strstr(reply_string, "T=");
+ if(!p){
+ printf("Bad reply from server.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ p += 2;
+ tmp = base64_decode(p, &tkt.dat);
+ if(tmp < 0){
+ printf("Failed to decode base64 in reply.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ tkt.length = tmp;
+ tktcopy.length = tkt.length;
+
+ p = strstr(reply_string, "P=");
+ if(!p){
+ printf("Bad reply from server.\n");
+ verbose = overbose;
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ name = p + 2;
+ for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
+ *p = 0;
+
+ snprintf(buf, sizeof(buf), "Password for %s:", name);
+ if (des_read_pw_string (passwd, sizeof(passwd)-1, buf, 0))
+ *passwd = '\0';
+ des_string_to_key (passwd, &key);
+
+ des_key_sched(&key, schedule);
+
+ des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
+ tkt.length,
+ schedule, &key, DES_DECRYPT);
+ if (strcmp ((char*)tktcopy.dat + 8,
+ KRB_TICKET_GRANTING_TICKET) != 0) {
+ afs_string_to_key (passwd, krb_realmofhost(hostname), &key);
+ des_key_sched (&key, schedule);
+ des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
+ tkt.length,
+ schedule, &key, DES_DECRYPT);
+ }
+ memset(key, 0, sizeof(key));
+ memset(schedule, 0, sizeof(schedule));
+ memset(passwd, 0, sizeof(passwd));
+ if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
+ printf("Out of memory base64-encoding.\n");
+ set_command_prot(save);
+ code = -1;
+ return;
+ }
+ memset (tktcopy.dat, 0, tktcopy.length);
+ ret = command("SITE KAUTH %s %s", name, p);
+ free(p);
+ set_command_prot(save);
+ if(ret != COMPLETE){
+ code = -1;
+ return;
+ }
+ code = 0;
+}
+
+void
+klist(int argc, char **argv)
+{
+ int ret;
+ if(argc != 1){
+ printf("usage: %s\n", argv[0]);
+ code = -1;
+ return;
+ }
+
+ ret = command("SITE KLIST");
+ code = (ret == COMPLETE);
+}
+
+void
+kdestroy(int argc, char **argv)
+{
+ int ret;
+ if (argc != 1) {
+ printf("usage: %s\n", argv[0]);
+ code = -1;
+ return;
+ }
+ ret = command("SITE KDESTROY");
+ code = (ret == COMPLETE);
+}
+
+void
+krbtkfile(int argc, char **argv)
+{
+ int ret;
+ if(argc != 2) {
+ printf("usage: %s tktfile\n", argv[0]);
+ code = -1;
+ return;
+ }
+ ret = command("SITE KRBTKFILE %s", argv[1]);
+ code = (ret == COMPLETE);
+}
+
+void
+afslog(int argc, char **argv)
+{
+ int ret;
+ if(argc > 2) {
+ printf("usage: %s [cell]\n", argv[0]);
+ code = -1;
+ return;
+ }
+ if(argc == 2)
+ ret = command("SITE AFSLOG %s", argv[1]);
+ else
+ ret = command("SITE AFSLOG");
+ code = (ret == COMPLETE);
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/krb4.c b/crypto/heimdal/appl/ftp/ftp/krb4.c
new file mode 100644
index 0000000..c89ba95
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/krb4.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
+#include "ftp_locl.h"
+#endif
+#include <krb.h>
+
+RCSID("$Id: krb4.c,v 1.37 1999/12/06 17:10:13 assar Exp $");
+
+#ifdef FTP_SERVER
+#define LOCAL_ADDR ctrl_addr
+#define REMOTE_ADDR his_addr
+#else
+#define LOCAL_ADDR myctladdr
+#define REMOTE_ADDR hisctladdr
+#endif
+
+extern struct sockaddr *LOCAL_ADDR, *REMOTE_ADDR;
+
+struct krb4_data {
+ des_cblock key;
+ des_key_schedule schedule;
+ char name[ANAME_SZ];
+ char instance[INST_SZ];
+ char realm[REALM_SZ];
+};
+
+static int
+krb4_check_prot(void *app_data, int level)
+{
+ if(level == prot_confidential)
+ return -1;
+ return 0;
+}
+
+static int
+krb4_decode(void *app_data, void *buf, int len, int level)
+{
+ MSG_DAT m;
+ int e;
+ struct krb4_data *d = app_data;
+
+ if(level == prot_safe)
+ e = krb_rd_safe(buf, len, &d->key,
+ (struct sockaddr_in *)REMOTE_ADDR,
+ (struct sockaddr_in *)LOCAL_ADDR, &m);
+ else
+ e = krb_rd_priv(buf, len, d->schedule, &d->key,
+ (struct sockaddr_in *)REMOTE_ADDR,
+ (struct sockaddr_in *)LOCAL_ADDR, &m);
+ if(e){
+ syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e));
+ return -1;
+ }
+ memmove(buf, m.app_data, m.app_length);
+ return m.app_length;
+}
+
+static int
+krb4_overhead(void *app_data, int level, int len)
+{
+ return 31;
+}
+
+static int
+krb4_encode(void *app_data, void *from, int length, int level, void **to)
+{
+ struct krb4_data *d = app_data;
+ *to = malloc(length + 31);
+ if(level == prot_safe)
+ return krb_mk_safe(from, *to, length, &d->key,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ else if(level == prot_private)
+ return krb_mk_priv(from, *to, length, d->schedule, &d->key,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ else
+ return -1;
+}
+
+#ifdef FTP_SERVER
+
+static int
+krb4_adat(void *app_data, void *buf, size_t len)
+{
+ KTEXT_ST tkt;
+ AUTH_DAT auth_dat;
+ char *p;
+ int kerror;
+ u_int32_t cs;
+ char msg[35]; /* size of encrypted block */
+ int tmp_len;
+ struct krb4_data *d = app_data;
+ char inst[INST_SZ];
+ struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr;
+
+ memcpy(tkt.dat, buf, len);
+ tkt.length = len;
+
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "ftp", inst,
+ his_addr_sin->sin_addr.s_addr, &auth_dat, "");
+ if(kerror == RD_AP_UNDEC){
+ k_getsockinst(0, inst, sizeof(inst));
+ kerror = krb_rd_req(&tkt, "rcmd", inst,
+ his_addr_sin->sin_addr.s_addr, &auth_dat, "");
+ }
+
+ if(kerror){
+ reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
+ return -1;
+ }
+
+ memcpy(d->key, auth_dat.session, sizeof(d->key));
+ des_set_key(&d->key, d->schedule);
+
+ strlcpy(d->name, auth_dat.pname, sizeof(d->name));
+ strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance));
+ strlcpy(d->realm, auth_dat.prealm, sizeof(d->instance));
+
+ cs = auth_dat.checksum + 1;
+ {
+ unsigned char tmp[4];
+ KRB_PUT_INT(cs, tmp, 4, sizeof(tmp));
+ tmp_len = krb_mk_safe(tmp, msg, 4, &d->key,
+ (struct sockaddr_in *)LOCAL_ADDR,
+ (struct sockaddr_in *)REMOTE_ADDR);
+ }
+ if(tmp_len < 0){
+ reply(535, "Error creating reply: %s.", strerror(errno));
+ return -1;
+ }
+ len = tmp_len;
+ if(base64_encode(msg, len, &p) < 0) {
+ reply(535, "Out of memory base64-encoding.");
+ return -1;
+ }
+ reply(235, "ADAT=%s", p);
+ sec_complete = 1;
+ free(p);
+ return 0;
+}
+
+static int
+krb4_userok(void *app_data, char *user)
+{
+ struct krb4_data *d = app_data;
+ return krb_kuserok(d->name, d->instance, d->realm, user);
+}
+
+struct sec_server_mech krb4_server_mech = {
+ "KERBEROS_V4",
+ sizeof(struct krb4_data),
+ NULL, /* init */
+ NULL, /* end */
+ krb4_check_prot,
+ krb4_overhead,
+ krb4_encode,
+ krb4_decode,
+ /* */
+ NULL,
+ krb4_adat,
+ NULL, /* pbsz */
+ NULL, /* ccc */
+ krb4_userok
+};
+
+#else /* FTP_SERVER */
+
+static int
+mk_auth(struct krb4_data *d, KTEXT adat,
+ char *service, char *host, int checksum)
+{
+ int ret;
+ CREDENTIALS cred;
+ char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
+
+ strlcpy(sname, service, sizeof(sname));
+ strlcpy(inst, krb_get_phost(host), sizeof(inst));
+ strlcpy(realm, krb_realmofhost(host), sizeof(realm));
+ ret = krb_mk_req(adat, sname, inst, realm, checksum);
+ if(ret)
+ return ret;
+ strlcpy(sname, service, sizeof(sname));
+ strlcpy(inst, krb_get_phost(host), sizeof(inst));
+ strlcpy(realm, krb_realmofhost(host), sizeof(realm));
+ ret = krb_get_cred(sname, inst, realm, &cred);
+ memmove(&d->key, &cred.session, sizeof(des_cblock));
+ des_key_sched(&d->key, d->schedule);
+ memset(&cred, 0, sizeof(cred));
+ return ret;
+}
+
+static int
+krb4_auth(void *app_data, char *host)
+{
+ int ret;
+ char *p;
+ int len;
+ KTEXT_ST adat;
+ MSG_DAT msg_data;
+ int checksum;
+ u_int32_t cs;
+ struct krb4_data *d = app_data;
+ struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
+ struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;
+
+ checksum = getpid();
+ ret = mk_auth(d, &adat, "ftp", host, checksum);
+ if(ret == KDC_PR_UNKNOWN)
+ ret = mk_auth(d, &adat, "rcmd", host, checksum);
+ if(ret){
+ printf("%s\n", krb_get_err_text(ret));
+ return AUTH_CONTINUE;
+ }
+
+#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
+ if (krb_get_config_bool("nat_in_use")) {
+ struct in_addr natAddr;
+
+ if (krb_get_our_ip_for_realm(krb_realmofhost(host),
+ &natAddr) != KSUCCESS
+ && krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
+ printf("Can't get address for realm %s\n",
+ krb_realmofhost(host));
+ else {
+ if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
+ printf("Using NAT IP address (%s) for kerberos 4\n",
+ inet_ntoa(natAddr));
+ localaddr->sin_addr = natAddr;
+
+ /*
+ * This not the best place to do this, but it
+ * is here we know that (probably) NAT is in
+ * use!
+ */
+
+ passivemode = 1;
+ printf("Setting: Passive mode on.\n");
+ }
+ }
+ }
+#endif
+
+ printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));
+ printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));
+
+ if(base64_encode(adat.dat, adat.length, &p) < 0) {
+ printf("Out of memory base64-encoding.\n");
+ return AUTH_CONTINUE;
+ }
+ ret = command("ADAT %s", p);
+ free(p);
+
+ if(ret != COMPLETE){
+ printf("Server didn't accept auth data.\n");
+ return AUTH_ERROR;
+ }
+
+ p = strstr(reply_string, "ADAT=");
+ if(!p){
+ printf("Remote host didn't send adat reply.\n");
+ return AUTH_ERROR;
+ }
+ p += 5;
+ len = base64_decode(p, adat.dat);
+ if(len < 0){
+ printf("Failed to decode base64 from server.\n");
+ return AUTH_ERROR;
+ }
+ adat.length = len;
+ ret = krb_rd_safe(adat.dat, adat.length, &d->key,
+ (struct sockaddr_in *)hisctladdr,
+ (struct sockaddr_in *)myctladdr, &msg_data);
+ if(ret){
+ printf("Error reading reply from server: %s.\n",
+ krb_get_err_text(ret));
+ return AUTH_ERROR;
+ }
+ krb_get_int(msg_data.app_data, &cs, 4, 0);
+ if(cs - checksum != 1){
+ printf("Bad checksum returned from server.\n");
+ return AUTH_ERROR;
+ }
+ return AUTH_OK;
+}
+
+struct sec_client_mech krb4_client_mech = {
+ "KERBEROS_V4",
+ sizeof(struct krb4_data),
+ NULL, /* init */
+ krb4_auth,
+ NULL, /* end */
+ krb4_check_prot,
+ krb4_overhead,
+ krb4_encode,
+ krb4_decode
+};
+
+#endif /* FTP_SERVER */
diff --git a/crypto/heimdal/appl/ftp/ftp/main.c b/crypto/heimdal/appl/ftp/ftp/main.c
new file mode 100644
index 0000000..dfe9e88
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/main.c
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * 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.
+ */
+
+/*
+ * FTP User Program -- Command Interface.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: main.c,v 1.27 1999/11/13 06:18:02 assar Exp $");
+
+int
+main(int argc, char **argv)
+{
+ int ch, top;
+ struct passwd *pw = NULL;
+ char homedir[MaxPathLen];
+ struct servent *sp;
+
+ set_progname(argv[0]);
+
+ sp = getservbyname("ftp", "tcp");
+ if (sp == 0)
+ errx(1, "ftp/tcp: unknown service");
+ doglob = 1;
+ interactive = 1;
+ autologin = 1;
+ passivemode = 0; /* passive mode not active */
+
+ while ((ch = getopt(argc, argv, "dginptv")) != -1) {
+ switch (ch) {
+ case 'd':
+ options |= SO_DEBUG;
+ debug++;
+ break;
+
+ case 'g':
+ doglob = 0;
+ break;
+
+ case 'i':
+ interactive = 0;
+ break;
+
+ case 'n':
+ autologin = 0;
+ break;
+
+ case 'p':
+ passivemode = 1;
+ break;
+ case 't':
+ trace++;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ default:
+ fprintf(stderr,
+ "usage: ftp [-dginptv] [host [port]]\n");
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ 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 = k_getpwuid(getuid());
+ if (pw != NULL) {
+ strlcpy(homedir, pw->pw_dir, sizeof(homedir));
+ home = homedir;
+ }
+ if (argc > 0) {
+ char *xargv[5];
+
+ if (setjmp(toplevel))
+ exit(0);
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+ xargv[0] = (char*)__progname;
+ xargv[1] = argv[0];
+ xargv[2] = argv[1];
+ xargv[3] = argv[2];
+ xargv[4] = NULL;
+ setpeer(argc+1, xargv);
+ }
+ if(setjmp(toplevel) == 0)
+ top = 1;
+ else
+ top = 0;
+ if (top) {
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+ }
+ for (;;) {
+ cmdscanner(top);
+ top = 1;
+ }
+}
+
+void
+intr(int sig)
+{
+
+ longjmp(toplevel, 1);
+}
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+RETSIGTYPE
+lostpeer(int sig)
+{
+
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), SHUT_RDWR);
+ fclose(cout);
+ cout = NULL;
+ }
+ if (data >= 0) {
+ shutdown(data, SHUT_RDWR);
+ close(data);
+ data = -1;
+ }
+ connected = 0;
+ }
+ pswitch(1);
+ if (connected) {
+ if (cout != NULL) {
+ shutdown(fileno(cout), SHUT_RDWR);
+ fclose(cout);
+ cout = NULL;
+ }
+ connected = 0;
+ }
+ proxflag = 0;
+ pswitch(0);
+ sec_end();
+ SIGRETURN(0);
+}
+
+/*
+char *
+tail(filename)
+ char *filename;
+{
+ char *s;
+
+ while (*filename) {
+ s = strrchr(filename, '/');
+ if (s == NULL)
+ break;
+ if (s[1])
+ return (s + 1);
+ *s = '\0';
+ }
+ return (filename);
+}
+*/
+
+#ifndef HAVE_READLINE
+
+static char *
+readline(char *prompt)
+{
+ char buf[BUFSIZ];
+ printf ("%s", prompt);
+ fflush (stdout);
+ if(fgets(buf, sizeof(buf), stdin) == NULL)
+ return NULL;
+ if (buf[strlen(buf) - 1] == '\n')
+ buf[strlen(buf) - 1] = '\0';
+ return strdup(buf);
+}
+
+static void
+add_history(char *p)
+{
+}
+
+#else
+
+/* These should not really be here */
+
+char *readline(char *);
+void add_history(char *);
+
+#endif
+
+/*
+ * Command parser.
+ */
+void
+cmdscanner(int top)
+{
+ struct cmd *c;
+ int l;
+
+ if (!top)
+ putchar('\n');
+ for (;;) {
+ if (fromatty) {
+ char *p;
+ p = readline("ftp> ");
+ if(p == NULL)
+ quit(0, 0);
+ strlcpy(line, p, sizeof(line));
+ add_history(p);
+ free(p);
+ } else{
+ if (fgets(line, sizeof line, stdin) == NULL)
+ quit(0, 0);
+ }
+ /* XXX will break on long lines */
+ 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 */
+ makeargv();
+ if (margc == 0) {
+ continue;
+ }
+ c = getcmd(margv[0]);
+ if (c == (struct cmd *)-1) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->c_conn && !connected) {
+ printf("Not connected.\n");
+ continue;
+ }
+ (*c->c_handler)(margc, margv);
+ if (bell && c->c_bell)
+ putchar('\007');
+ if (c->c_handler != help)
+ break;
+ }
+ signal(SIGINT, intr);
+ signal(SIGPIPE, lostpeer);
+}
+
+struct cmd *
+getcmd(char *name)
+{
+ char *p, *q;
+ struct cmd *c, *found;
+ int nmatches, longest;
+
+ longest = 0;
+ nmatches = 0;
+ found = 0;
+ for (c = cmdtab; (p = c->c_name); 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;
+
+void
+makeargv(void)
+{
+ char **argp;
+
+ argp = margv;
+ stringbase = line; /* scan from first of buffer */
+ argbase = argbuf; /* store from first of buffer */
+ slrflag = 0;
+ for (margc = 0; ; margc++) {
+ /* Expand array if necessary */
+ if (margc == margvlen) {
+ int i;
+
+ margv = (margvlen == 0)
+ ? (char **)malloc(20 * sizeof(char *))
+ : (char **)realloc(margv,
+ (margvlen + 20)*sizeof(char *));
+ if (margv == NULL)
+ errx(1, "cannot realloc argv array");
+ for(i = margvlen; i < margvlen + 20; ++i)
+ margv[i] = NULL;
+ margvlen += 20;
+ argp = margv + margc;
+ }
+
+ if ((*argp++ = slurpstring()) == NULL)
+ break;
+ }
+
+}
+
+/*
+ * Parse string into argbuf;
+ * implemented with FSM to
+ * handle quoting and strings
+ */
+char *
+slurpstring(void)
+{
+ int got_one = 0;
+ char *sb = stringbase;
+ 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 == '!') ? "!" : "$");
+ /* 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 = (char *) 0;
+ 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, 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++) {
+ putchar(' ');
+ }
+ }
+ if (c + lines >= &cmdtab[NCMDS]) {
+ printf("\n");
+ break;
+ }
+ w = strlen(c->c_name);
+ while (w < width) {
+ w = (w + 8) &~ 7;
+ putchar('\t');
+ }
+ }
+ }
+ return;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (c == (struct cmd *)-1)
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (struct cmd *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%-*s\t%s\n", HELPINDENT,
+ c->c_name, c->c_help);
+ }
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/pathnames.h b/crypto/heimdal/appl/ftp/ftp/pathnames.h
new file mode 100644
index 0000000..f7c1fb3
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/pathnames.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1989, 1993
+ * 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#define _PATH_TMP_XXX "/tmp/ftpXXXXXX"
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
diff --git a/crypto/heimdal/appl/ftp/ftp/ruserpass.c b/crypto/heimdal/appl/ftp/ftp/ruserpass.c
new file mode 100644
index 0000000..b22f699
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/ruserpass.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 1985, 1993, 1994
+ * 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.
+ */
+
+#include "ftp_locl.h"
+RCSID("$Id: ruserpass.c,v 1.19 2000/01/08 07:45:11 assar Exp $");
+
+static int token (void);
+static FILE *cfile;
+
+#define DEFAULT 1
+#define LOGIN 2
+#define PASSWD 3
+#define ACCOUNT 4
+#define MACDEF 5
+#define PROT 6
+#define ID 10
+#define MACH 11
+
+static char tokval[100];
+
+static struct toktab {
+ char *tokstr;
+ int tval;
+} toktab[]= {
+ { "default", DEFAULT },
+ { "login", LOGIN },
+ { "password", PASSWD },
+ { "passwd", PASSWD },
+ { "account", ACCOUNT },
+ { "machine", MACH },
+ { "macdef", MACDEF },
+ { "prot", PROT },
+ { NULL, 0 }
+};
+
+/*
+ * Write a copy of the hostname into `hostname, sz' and return a guess
+ * as to the `domain' of that hostname.
+ */
+
+static char *
+guess_domain (char *hostname, size_t sz)
+{
+ struct addrinfo *ai, *a;
+ struct addrinfo hints;
+ int error;
+ char *dot;
+
+ if (gethostname (hostname, sz) < 0) {
+ strlcpy (hostname, "", sz);
+ return "";
+ }
+ dot = strchr (hostname, '.');
+ if (dot != NULL)
+ return dot + 1;
+
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+
+ error = getaddrinfo (hostname, NULL, &hints, &ai);
+ if (error)
+ return hostname;
+
+ for (a = ai; a != NULL; a = a->ai_next)
+ if (a->ai_canonname != NULL) {
+ strlcpy (hostname, ai->ai_canonname, sz);
+ break;
+ }
+ freeaddrinfo (ai);
+ dot = strchr (hostname, '.');
+ if (dot != NULL)
+ return dot + 1;
+ else
+ return hostname;
+}
+
+int
+ruserpass(char *host, char **aname, char **apass, char **aacct)
+{
+ char *hdir, buf[BUFSIZ], *tmp;
+ int t, i, c, usedefault = 0;
+ struct stat stb;
+
+ mydomain = guess_domain (myhostname, MaxHostNameLen);
+
+ hdir = getenv("HOME");
+ if (hdir == NULL)
+ hdir = ".";
+ snprintf(buf, sizeof(buf), "%s/.netrc", hdir);
+ cfile = fopen(buf, "r");
+ if (cfile == NULL) {
+ if (errno != ENOENT)
+ warn("%s", buf);
+ return (0);
+ }
+
+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 = strchr(hostname, '.')) != NULL &&
+ tmp++ &&
+ strcasecmp(tmp, mydomain) == 0 &&
+ strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
+ tokval[tmp - hostname] == '\0')
+ goto match;
+ if ((tmp = strchr(host, '.')) != NULL &&
+ tmp++ &&
+ 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 = strdup(tokval);
+ } else {
+ if (strcmp(*aname, tokval))
+ goto next;
+ }
+ }
+ break;
+ case PASSWD:
+ if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
+ fstat(fileno(cfile), &stb) >= 0 &&
+ (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove password or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *apass == 0) {
+ *apass = strdup(tokval);
+ }
+ break;
+ case ACCOUNT:
+ if (fstat(fileno(cfile), &stb) >= 0
+ && (stb.st_mode & 077) != 0) {
+ warnx("Error: .netrc file is readable by others.");
+ warnx("Remove account or make file unreadable by others.");
+ goto bad;
+ }
+ if (token() && *aacct == 0) {
+ *aacct = strdup(tokval);
+ }
+ break;
+ case MACDEF:
+ if (proxy) {
+ 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 + 4096) {
+ 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 + 4096) {
+ printf("4K macro buffer exceeded\n");
+ goto bad;
+ }
+ break;
+ case PROT:
+ token();
+ if(sec_request_prot(tokval) < 0)
+ warnx("Unknown protection level \"%s\"", tokval);
+ break;
+ default:
+ warnx("Unknown .netrc keyword %s", tokval);
+ break;
+ }
+ goto done;
+ }
+done:
+ fclose(cfile);
+ return (0);
+bad:
+ fclose(cfile);
+ return (-1);
+}
+
+static int
+token(void)
+{
+ char *cp;
+ int c;
+ struct toktab *t;
+
+ if (feof(cfile) || ferror(cfile))
+ return (0);
+ while ((c = getc(cfile)) != EOF &&
+ (c == '\n' || c == '\t' || c == ' ' || c == ','))
+ continue;
+ if (c == EOF)
+ return (0);
+ cp = tokval;
+ if (c == '"') {
+ while ((c = getc(cfile)) != EOF && c != '"') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ } else {
+ *cp++ = c;
+ while ((c = getc(cfile)) != EOF
+ && c != '\n' && c != '\t' && c != ' ' && c != ',') {
+ if (c == '\\')
+ c = getc(cfile);
+ *cp++ = c;
+ }
+ }
+ *cp = 0;
+ if (tokval[0] == 0)
+ return (0);
+ for (t = toktab; t->tokstr; t++)
+ if (!strcmp(t->tokstr, tokval))
+ return (t->tval);
+ return (ID);
+}
diff --git a/crypto/heimdal/appl/ftp/ftp/security.c b/crypto/heimdal/appl/ftp/ftp/security.c
new file mode 100644
index 0000000..ca7eb00
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/security.c
@@ -0,0 +1,785 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef FTP_SERVER
+#include "ftpd_locl.h"
+#else
+#include "ftp_locl.h"
+#endif
+
+RCSID("$Id: security.c,v 1.15 1999/12/02 16:58:30 joda Exp $");
+
+static enum protection_level command_prot;
+static enum protection_level data_prot;
+static size_t buffer_size;
+
+struct buffer {
+ void *data;
+ size_t size;
+ size_t index;
+ int eof_flag;
+};
+
+static struct buffer in_buffer, out_buffer;
+int sec_complete;
+
+static struct {
+ enum protection_level level;
+ const char *name;
+} level_names[] = {
+ { prot_clear, "clear" },
+ { prot_safe, "safe" },
+ { prot_confidential, "confidential" },
+ { prot_private, "private" }
+};
+
+static const char *
+level_to_name(enum protection_level level)
+{
+ int i;
+ for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
+ if(level_names[i].level == level)
+ return level_names[i].name;
+ return "unknown";
+}
+
+#ifndef FTP_SERVER /* not used in server */
+static enum protection_level
+name_to_level(const char *name)
+{
+ int i;
+ for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
+ if(!strncasecmp(level_names[i].name, name, strlen(name)))
+ return level_names[i].level;
+ return (enum protection_level)-1;
+}
+#endif
+
+#ifdef FTP_SERVER
+
+static struct sec_server_mech *mechs[] = {
+#ifdef KRB5
+ &gss_server_mech,
+#endif
+#ifdef KRB4
+ &krb4_server_mech,
+#endif
+ NULL
+};
+
+static struct sec_server_mech *mech;
+
+#else
+
+static struct sec_client_mech *mechs[] = {
+#ifdef KRB5
+ &gss_client_mech,
+#endif
+#ifdef KRB4
+ &krb4_client_mech,
+#endif
+ NULL
+};
+
+static struct sec_client_mech *mech;
+
+#endif
+
+static void *app_data;
+
+int
+sec_getc(FILE *F)
+{
+ if(sec_complete && data_prot) {
+ char c;
+ if(sec_read(fileno(F), &c, 1) <= 0)
+ return EOF;
+ return c;
+ } else
+ return getc(F);
+}
+
+static int
+block_read(int fd, void *buf, size_t len)
+{
+ unsigned char *p = buf;
+ int b;
+ while(len) {
+ b = read(fd, p, len);
+ if (b == 0)
+ return 0;
+ else if (b < 0)
+ return -1;
+ len -= b;
+ p += b;
+ }
+ return p - (unsigned char*)buf;
+}
+
+static int
+block_write(int fd, void *buf, size_t len)
+{
+ unsigned char *p = buf;
+ int b;
+ while(len) {
+ b = write(fd, p, len);
+ if(b < 0)
+ return -1;
+ len -= b;
+ p += b;
+ }
+ return p - (unsigned char*)buf;
+}
+
+static int
+sec_get_data(int fd, struct buffer *buf, int level)
+{
+ int len;
+ int b;
+
+ b = block_read(fd, &len, sizeof(len));
+ if (b == 0)
+ return 0;
+ else if (b < 0)
+ return -1;
+ len = ntohl(len);
+ buf->data = realloc(buf->data, len);
+ b = block_read(fd, buf->data, len);
+ if (b == 0)
+ return 0;
+ else if (b < 0)
+ return -1;
+ buf->size = (*mech->decode)(app_data, buf->data, len, data_prot);
+ buf->index = 0;
+ return 0;
+}
+
+static size_t
+buffer_read(struct buffer *buf, void *data, size_t len)
+{
+ len = min(len, buf->size - buf->index);
+ memcpy(data, (char*)buf->data + buf->index, len);
+ buf->index += len;
+ return len;
+}
+
+static size_t
+buffer_write(struct buffer *buf, void *data, size_t len)
+{
+ if(buf->index + len > buf->size) {
+ void *tmp;
+ if(buf->data == NULL)
+ tmp = malloc(1024);
+ else
+ tmp = realloc(buf->data, buf->index + len);
+ if(tmp == NULL)
+ return -1;
+ buf->data = tmp;
+ buf->size = buf->index + len;
+ }
+ memcpy((char*)buf->data + buf->index, data, len);
+ buf->index += len;
+ return len;
+}
+
+int
+sec_read(int fd, void *data, int length)
+{
+ size_t len;
+ int rx = 0;
+
+ if(sec_complete == 0 || data_prot == 0)
+ return read(fd, data, length);
+
+ if(in_buffer.eof_flag){
+ in_buffer.eof_flag = 0;
+ return 0;
+ }
+
+ len = buffer_read(&in_buffer, data, length);
+ length -= len;
+ rx += len;
+ data = (char*)data + len;
+
+ while(length){
+ if(sec_get_data(fd, &in_buffer, data_prot) < 0)
+ return -1;
+ if(in_buffer.size == 0) {
+ if(rx)
+ in_buffer.eof_flag = 1;
+ return rx;
+ }
+ len = buffer_read(&in_buffer, data, length);
+ length -= len;
+ rx += len;
+ data = (char*)data + len;
+ }
+ return rx;
+}
+
+static int
+sec_send(int fd, char *from, int length)
+{
+ int bytes;
+ void *buf;
+ bytes = (*mech->encode)(app_data, from, length, data_prot, &buf);
+ bytes = htonl(bytes);
+ block_write(fd, &bytes, sizeof(bytes));
+ block_write(fd, buf, ntohl(bytes));
+ free(buf);
+ return length;
+}
+
+int
+sec_fflush(FILE *F)
+{
+ if(data_prot != prot_clear) {
+ if(out_buffer.index > 0){
+ sec_write(fileno(F), out_buffer.data, out_buffer.index);
+ out_buffer.index = 0;
+ }
+ sec_send(fileno(F), NULL, 0);
+ }
+ fflush(F);
+ return 0;
+}
+
+int
+sec_write(int fd, char *data, int length)
+{
+ int len = buffer_size;
+ int tx = 0;
+
+ if(data_prot == prot_clear)
+ return write(fd, data, length);
+
+ len -= (*mech->overhead)(app_data, data_prot, len);
+ while(length){
+ if(length < len)
+ len = length;
+ sec_send(fd, data, len);
+ length -= len;
+ data += len;
+ tx += len;
+ }
+ return tx;
+}
+
+int
+sec_vfprintf2(FILE *f, const char *fmt, va_list ap)
+{
+ char *buf;
+ int ret;
+ if(data_prot == prot_clear)
+ return vfprintf(f, fmt, ap);
+ else {
+ vasprintf(&buf, fmt, ap);
+ ret = buffer_write(&out_buffer, buf, strlen(buf));
+ free(buf);
+ return ret;
+ }
+}
+
+int
+sec_fprintf2(FILE *f, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+ va_start(ap, fmt);
+ ret = sec_vfprintf2(f, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+int
+sec_putc(int c, FILE *F)
+{
+ char ch = c;
+ if(data_prot == prot_clear)
+ return putc(c, F);
+
+ buffer_write(&out_buffer, &ch, 1);
+ if(c == '\n' || out_buffer.index >= 1024 /* XXX */) {
+ sec_write(fileno(F), out_buffer.data, out_buffer.index);
+ out_buffer.index = 0;
+ }
+ return c;
+}
+
+int
+sec_read_msg(char *s, int level)
+{
+ int len;
+ char *buf;
+ int code;
+
+ buf = malloc(strlen(s));
+ len = base64_decode(s + 4, buf); /* XXX */
+
+ len = (*mech->decode)(app_data, buf, len, level);
+ if(len < 0)
+ return -1;
+
+ buf[len] = '\0';
+
+ if(buf[3] == '-')
+ code = 0;
+ else
+ sscanf(buf, "%d", &code);
+ if(buf[len-1] == '\n')
+ buf[len-1] = '\0';
+ strcpy(s, buf);
+ free(buf);
+ return code;
+}
+
+int
+sec_vfprintf(FILE *f, const char *fmt, va_list ap)
+{
+ char *buf;
+ void *enc;
+ int len;
+ if(!sec_complete)
+ return vfprintf(f, fmt, ap);
+
+ vasprintf(&buf, fmt, ap);
+ len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc);
+ free(buf);
+ if(len < 0) {
+ printf("Failed to encode command.\n");
+ return -1;
+ }
+ if(base64_encode(enc, len, &buf) < 0){
+ printf("Out of memory base64-encoding.\n");
+ return -1;
+ }
+#ifdef FTP_SERVER
+ if(command_prot == prot_safe)
+ fprintf(f, "631 %s\r\n", buf);
+ else if(command_prot == prot_private)
+ fprintf(f, "632 %s\r\n", buf);
+ else if(command_prot == prot_confidential)
+ fprintf(f, "633 %s\r\n", buf);
+#else
+ if(command_prot == prot_safe)
+ fprintf(f, "MIC %s", buf);
+ else if(command_prot == prot_private)
+ fprintf(f, "ENC %s", buf);
+ else if(command_prot == prot_confidential)
+ fprintf(f, "CONF %s", buf);
+#endif
+ free(buf);
+ return 0;
+}
+
+int
+sec_fprintf(FILE *f, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+ va_start(ap, fmt);
+ ret = sec_vfprintf(f, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+
+/* end common stuff */
+
+#ifdef FTP_SERVER
+
+void
+auth(char *auth_name)
+{
+ int i;
+ for(i = 0; (mech = mechs[i]) != NULL; i++){
+ if(!strcasecmp(auth_name, mech->name)){
+ app_data = realloc(app_data, mech->size);
+ if(mech->init && (*mech->init)(app_data) != 0) {
+ reply(431, "Unable to accept %s at this time", mech->name);
+ return;
+ }
+ if(mech->auth) {
+ (*mech->auth)(app_data);
+ return;
+ }
+ if(mech->adat)
+ reply(334, "Send authorization data.");
+ else
+ reply(234, "Authorization complete.");
+ return;
+ }
+ }
+ free (app_data);
+ reply(504, "%s is unknown to me", auth_name);
+}
+
+void
+adat(char *auth_data)
+{
+ if(mech && !sec_complete) {
+ void *buf = malloc(strlen(auth_data));
+ size_t len;
+ len = base64_decode(auth_data, buf);
+ (*mech->adat)(app_data, buf, len);
+ free(buf);
+ } else
+ reply(503, "You must %sissue an AUTH first.", mech ? "re-" : "");
+}
+
+void pbsz(int size)
+{
+ size_t new = size;
+ if(!sec_complete)
+ reply(503, "Incomplete security data exchange.");
+ if(mech->pbsz)
+ new = (*mech->pbsz)(app_data, size);
+ if(buffer_size != new){
+ buffer_size = size;
+ }
+ if(new != size)
+ reply(200, "PBSZ=%lu", (unsigned long)new);
+ else
+ reply(200, "OK");
+}
+
+void
+prot(char *pl)
+{
+ int p = -1;
+
+ if(buffer_size == 0){
+ reply(503, "No protection buffer size negotiated.");
+ return;
+ }
+
+ if(!strcasecmp(pl, "C"))
+ p = prot_clear;
+ else if(!strcasecmp(pl, "S"))
+ p = prot_safe;
+ else if(!strcasecmp(pl, "E"))
+ p = prot_confidential;
+ else if(!strcasecmp(pl, "P"))
+ p = prot_private;
+ else {
+ reply(504, "Unrecognized protection level.");
+ return;
+ }
+
+ if(sec_complete){
+ if((*mech->check_prot)(app_data, p)){
+ reply(536, "%s does not support %s protection.",
+ mech->name, level_to_name(p));
+ }else{
+ data_prot = (enum protection_level)p;
+ reply(200, "Data protection is %s.", level_to_name(p));
+ }
+ }else{
+ reply(503, "Incomplete security data exchange.");
+ }
+}
+
+void ccc(void)
+{
+ if(sec_complete){
+ if(mech->ccc && (*mech->ccc)(app_data) == 0)
+ command_prot = data_prot = prot_clear;
+ else
+ reply(534, "You must be joking.");
+ }else
+ reply(503, "Incomplete security data exchange.");
+}
+
+void mec(char *msg, enum protection_level level)
+{
+ void *buf;
+ size_t len;
+ if(!sec_complete) {
+ reply(503, "Incomplete security data exchange.");
+ return;
+ }
+ buf = malloc(strlen(msg) + 2); /* XXX go figure out where that 2
+ comes from :-) */
+ len = base64_decode(msg, buf);
+ command_prot = level;
+ if(len == (size_t)-1) {
+ reply(501, "Failed to base64-decode command");
+ return;
+ }
+ len = (*mech->decode)(app_data, buf, len, level);
+ if(len == (size_t)-1) {
+ reply(535, "Failed to decode command");
+ return;
+ }
+ ((char*)buf)[len] = '\0';
+ if(strstr((char*)buf, "\r\n") == NULL)
+ strcat((char*)buf, "\r\n");
+ new_ftp_command(buf);
+}
+
+/* ------------------------------------------------------------ */
+
+int
+sec_userok(char *user)
+{
+ if(sec_complete)
+ return (*mech->userok)(app_data, user);
+ return 0;
+}
+
+char *ftp_command;
+
+void
+new_ftp_command(char *command)
+{
+ ftp_command = command;
+}
+
+void
+delete_ftp_command(void)
+{
+ free(ftp_command);
+ ftp_command = NULL;
+}
+
+int
+secure_command(void)
+{
+ return ftp_command != NULL;
+}
+
+enum protection_level
+get_command_prot(void)
+{
+ return command_prot;
+}
+
+#else /* FTP_SERVER */
+
+void
+sec_status(void)
+{
+ if(sec_complete){
+ printf("Using %s for authentication.\n", mech->name);
+ printf("Using %s command channel.\n", level_to_name(command_prot));
+ printf("Using %s data channel.\n", level_to_name(data_prot));
+ if(buffer_size > 0)
+ printf("Protection buffer size: %lu.\n",
+ (unsigned long)buffer_size);
+ }else{
+ printf("Not using any security mechanism.\n");
+ }
+}
+
+static int
+sec_prot_internal(int level)
+{
+ int ret;
+ char *p;
+ unsigned int s = 1048576;
+
+ int old_verbose = verbose;
+ verbose = 0;
+
+ if(!sec_complete){
+ printf("No security data exchange has taken place.\n");
+ return -1;
+ }
+
+ if(level){
+ ret = command("PBSZ %u", s);
+ if(ret != COMPLETE){
+ printf("Failed to set protection buffer size.\n");
+ return -1;
+ }
+ buffer_size = s;
+ p = strstr(reply_string, "PBSZ=");
+ if(p)
+ sscanf(p, "PBSZ=%u", &s);
+ if(s < buffer_size)
+ buffer_size = s;
+ }
+ verbose = old_verbose;
+ ret = command("PROT %c", level["CSEP"]); /* XXX :-) */
+ if(ret != COMPLETE){
+ printf("Failed to set protection level.\n");
+ return -1;
+ }
+
+ data_prot = (enum protection_level)level;
+ return 0;
+}
+
+enum protection_level
+set_command_prot(enum protection_level level)
+{
+ enum protection_level old = command_prot;
+ command_prot = level;
+ return old;
+}
+
+void
+sec_prot(int argc, char **argv)
+{
+ int level = -1;
+
+ if(argc < 2 || argc > 3)
+ goto usage;
+ if(!sec_complete) {
+ printf("No security data exchange has taken place.\n");
+ code = -1;
+ return;
+ }
+ level = name_to_level(argv[argc - 1]);
+
+ if(level == -1)
+ goto usage;
+
+ if((*mech->check_prot)(app_data, level)) {
+ printf("%s does not implement %s protection.\n",
+ mech->name, level_to_name(level));
+ code = -1;
+ return;
+ }
+
+ if(argc == 2 || strncasecmp(argv[1], "data", strlen(argv[1])) == 0) {
+ if(sec_prot_internal(level) < 0){
+ code = -1;
+ return;
+ }
+ } else if(strncasecmp(argv[1], "command", strlen(argv[1])) == 0)
+ set_command_prot(level);
+ else
+ goto usage;
+ code = 0;
+ return;
+ usage:
+ printf("usage: %s [command|data] [clear|safe|confidential|private]\n",
+ argv[0]);
+ code = -1;
+}
+
+static enum protection_level request_data_prot;
+
+void
+sec_set_protection_level(void)
+{
+ if(sec_complete && data_prot != request_data_prot)
+ sec_prot_internal(request_data_prot);
+}
+
+
+int
+sec_request_prot(char *level)
+{
+ int l = name_to_level(level);
+ if(l == -1)
+ return -1;
+ request_data_prot = (enum protection_level)l;
+ return 0;
+}
+
+int
+sec_login(char *host)
+{
+ int ret;
+ struct sec_client_mech **m;
+ int old_verbose = verbose;
+
+ verbose = -1; /* shut up all messages this will produce (they
+ are usually not very user friendly) */
+
+ for(m = mechs; *m && (*m)->name; m++) {
+ void *tmp;
+
+ tmp = realloc(app_data, (*m)->size);
+ if (tmp == NULL) {
+ warnx ("realloc %u failed", (*m)->size);
+ return -1;
+ }
+ app_data = tmp;
+
+ if((*m)->init && (*(*m)->init)(app_data) != 0) {
+ printf("Skipping %s...\n", (*m)->name);
+ continue;
+ }
+ printf("Trying %s...\n", (*m)->name);
+ ret = command("AUTH %s", (*m)->name);
+ if(ret != CONTINUE){
+ if(code == 504){
+ printf("%s is not supported by the server.\n", (*m)->name);
+ }else if(code == 534){
+ printf("%s rejected as security mechanism.\n", (*m)->name);
+ }else if(ret == ERROR) {
+ printf("The server doesn't support the FTP "
+ "security extensions.\n");
+ verbose = old_verbose;
+ return -1;
+ }
+ continue;
+ }
+
+ ret = (*(*m)->auth)(app_data, host);
+
+ if(ret == AUTH_CONTINUE)
+ continue;
+ else if(ret != AUTH_OK){
+ /* mechanism is supposed to output error string */
+ verbose = old_verbose;
+ return -1;
+ }
+ mech = *m;
+ sec_complete = 1;
+ command_prot = prot_safe;
+ break;
+ }
+
+ verbose = old_verbose;
+ return *m == NULL;
+}
+
+void
+sec_end(void)
+{
+ if (mech != NULL) {
+ if(mech->end)
+ (*mech->end)(app_data);
+ memset(app_data, 0, mech->size);
+ free(app_data);
+ app_data = NULL;
+ }
+ sec_complete = 0;
+ data_prot = (enum protection_level)0;
+}
+
+#endif /* FTP_SERVER */
+
diff --git a/crypto/heimdal/appl/ftp/ftp/security.h b/crypto/heimdal/appl/ftp/ftp/security.h
new file mode 100644
index 0000000..6fe0694
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftp/security.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: security.h,v 1.7 1999/12/02 16:58:30 joda Exp $ */
+
+#ifndef __security_h__
+#define __security_h__
+
+enum protection_level {
+ prot_clear,
+ prot_safe,
+ prot_confidential,
+ prot_private
+};
+
+struct sec_client_mech {
+ char *name;
+ size_t size;
+ int (*init)(void *);
+ int (*auth)(void *, char*);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, void*, int, int, void**);
+ int (*decode)(void *, void*, int, int);
+};
+
+struct sec_server_mech {
+ char *name;
+ size_t size;
+ int (*init)(void *);
+ void (*end)(void *);
+ int (*check_prot)(void *, int);
+ int (*overhead)(void *, int, int);
+ int (*encode)(void *, void*, int, int, void**);
+ int (*decode)(void *, void*, int, int);
+
+ int (*auth)(void *);
+ int (*adat)(void *, void*, size_t);
+ size_t (*pbsz)(void *, size_t);
+ int (*ccc)(void*);
+ int (*userok)(void*, char*);
+};
+
+#define AUTH_OK 0
+#define AUTH_CONTINUE 1
+#define AUTH_ERROR 2
+
+#ifdef FTP_SERVER
+extern struct sec_server_mech krb4_server_mech, gss_server_mech;
+#else
+extern struct sec_client_mech krb4_client_mech, gss_client_mech;
+#endif
+
+extern int sec_complete;
+
+#ifdef FTP_SERVER
+extern char *ftp_command;
+void new_ftp_command(char*);
+void delete_ftp_command(void);
+#endif
+
+/* ---- */
+
+
+int sec_fflush (FILE *);
+int sec_fprintf (FILE *, const char *, ...);
+int sec_getc (FILE *);
+int sec_putc (int, FILE *);
+int sec_read (int, void *, int);
+int sec_read_msg (char *, int);
+int sec_vfprintf (FILE *, const char *, va_list);
+int sec_fprintf2(FILE *f, const char *fmt, ...);
+int sec_vfprintf2(FILE *, const char *, va_list);
+int sec_write (int, char *, int);
+
+#ifdef FTP_SERVER
+void adat (char *);
+void auth (char *);
+void ccc (void);
+void mec (char *, enum protection_level);
+void pbsz (int);
+void prot (char *);
+void delete_ftp_command (void);
+void new_ftp_command (char *);
+int sec_userok (char *);
+int secure_command (void);
+enum protection_level get_command_prot(void);
+#else
+void sec_end (void);
+int sec_login (char *);
+void sec_prot (int, char **);
+int sec_request_prot (char *);
+void sec_set_protection_level (void);
+void sec_status (void);
+
+enum protection_level set_command_prot(enum protection_level);
+
+#endif
+
+#endif /* __security_h__ */
diff --git a/crypto/heimdal/appl/ftp/ftpd/Makefile.am b/crypto/heimdal/appl/ftp/ftpd/Makefile.am
new file mode 100644
index 0000000..92d8e7c
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/Makefile.am
@@ -0,0 +1,56 @@
+# $Id: Makefile.am,v 1.21 2000/01/06 15:10:57 assar Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+INCLUDES += -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER
+
+libexec_PROGRAMS = ftpd
+
+CHECK_LOCAL =
+
+if KRB4
+krb4_sources = krb4.c kauth.c
+endif
+if KRB5
+krb5_sources = gssapi.c gss_userok.c
+endif
+
+ftpd_SOURCES = \
+ extern.h \
+ ftpcmd.y \
+ ftpd.c \
+ ftpd_locl.h \
+ logwtmp.c \
+ ls.c \
+ pathnames.h \
+ popen.c \
+ security.c \
+ $(krb4_sources) \
+ $(krb5_sources)
+
+EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c
+
+$(ftpd_OBJECTS): security.h
+
+security.c:
+ @test -f security.c || $(LN_S) $(srcdir)/../ftp/security.c .
+security.h:
+ @test -f security.h || $(LN_S) $(srcdir)/../ftp/security.h .
+krb4.c:
+ @test -f krb4.c || $(LN_S) $(srcdir)/../ftp/krb4.c .
+gssapi.c:
+ @test -f gssapi.c || $(LN_S) $(srcdir)/../ftp/gssapi.c .
+
+CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c
+
+man_MANS = ftpd.8 ftpusers.5
+
+LDADD = ../common/libcommon.a \
+ $(LIB_kafs) \
+ $(LIB_gssapi) \
+ $(LIB_krb5) \
+ $(LIB_krb4) \
+ $(LIB_otp) \
+ $(top_builddir)/lib/des/libdes.la \
+ $(LIB_roken) \
+ $(DBLIB)
diff --git a/crypto/heimdal/appl/ftp/ftpd/Makefile.in b/crypto/heimdal/appl/ftp/ftpd/Makefile.in
new file mode 100644
index 0000000..1cd211b
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/Makefile.in
@@ -0,0 +1,768 @@
+# Makefile.in generated automatically by automake 1.4 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+# $Id: Makefile.am,v 1.21 2000/01/06 15:10:57 assar Exp $
+
+
+# $Id: Makefile.am.common,v 1.3 1999/04/01 14:58:43 joda Exp $
+
+
+# $Id: Makefile.am.common,v 1.13 1999/11/01 03:19:58 assar Exp $
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+AFS_EXTRA_LD = @AFS_EXTRA_LD@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CC = @CC@
+DBLIB = @DBLIB@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+GROFF = @GROFF@
+INCLUDE_ = @INCLUDE_@
+LD = @LD@
+LEX = @LEX@
+LIBOBJS = @LIBOBJS@
+LIBTOOL = @LIBTOOL@
+LIB_ = @LIB_@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_kdb = @LIB_kdb@
+LIB_otp = @LIB_otp@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_X_PROGS_BIN_PROGS = @MAKE_X_PROGS_BIN_PROGS@
+MAKE_X_PROGS_BIN_SCRPTS = @MAKE_X_PROGS_BIN_SCRPTS@
+MAKE_X_PROGS_LIBEXEC_PROGS = @MAKE_X_PROGS_LIBEXEC_PROGS@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NM = @NM@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+YACC = @YACC@
+
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+SUFFIXES = .et .h .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .x
+
+INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../common $(INCLUDE_krb4) -DFTP_SERVER
+
+AM_CFLAGS = $(WFLAGS)
+
+COMPILE_ET = $(top_builddir)/lib/com_err/compile_et
+
+buildinclude = $(top_builddir)/include
+
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_crypt = @LIB_crypt@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_el_init = @LIB_el_init@
+LIB_getattr = @LIB_getattr@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_readline = @LIB_readline@
+LIB_res_search = @LIB_res_search@
+LIB_setpcred = @LIB_setpcred@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+LIB_hesiod = @LIB_hesiod@
+
+INCLUDE_krb4 = @INCLUDE_krb4@
+LIB_krb4 = @LIB_krb4@
+
+INCLUDE_readline = @INCLUDE_readline@
+
+LEXLIB = @LEXLIB@
+
+cat1dir = $(mandir)/cat1
+cat3dir = $(mandir)/cat3
+cat5dir = $(mandir)/cat5
+cat8dir = $(mandir)/cat8
+
+MANRX = \(.*\)\.\([0-9]\)
+CATSUFFIX = @CATSUFFIX@
+
+NROFF_MAN = groff -mandoc -Tascii
+
+@KRB4_TRUE@LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la $(top_builddir)/lib/asn1/libasn1.la
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+
+CHECK_LOCAL =
+
+libexec_PROGRAMS = ftpd
+
+@KRB4_TRUE@krb4_sources = krb4.c kauth.c
+@KRB5_TRUE@krb5_sources = gssapi.c gss_userok.c
+
+ftpd_SOURCES = extern.h ftpcmd.y ftpd.c ftpd_locl.h logwtmp.c ls.c pathnames.h popen.c security.c $(krb4_sources) $(krb5_sources)
+
+
+EXTRA_ftpd_SOURCES = krb4.c kauth.c gssapi.c gss_userok.c
+
+CLEANFILES = security.c security.h krb4.c gssapi.c ftpcmd.c
+
+man_MANS = ftpd.8 ftpusers.5
+
+LDADD = ../common/libcommon.a $(LIB_kafs) $(LIB_gssapi) $(LIB_krb5) $(LIB_krb4) $(LIB_otp) $(top_builddir)/lib/des/libdes.la $(LIB_roken) $(DBLIB)
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../../../include/config.h
+CONFIG_CLEAN_FILES =
+libexec_PROGRAMS = ftpd$(EXEEXT)
+PROGRAMS = $(libexec_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../../../include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+@KRB4_TRUE@@KRB5_FALSE@ftpd_OBJECTS = ftpcmd.$(OBJEXT) ftpd.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@logwtmp.$(OBJEXT) ls.$(OBJEXT) popen.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@security.$(OBJEXT) krb4.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_FALSE@kauth.$(OBJEXT)
+@KRB4_FALSE@@KRB5_TRUE@ftpd_OBJECTS = ftpcmd.$(OBJEXT) ftpd.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@logwtmp.$(OBJEXT) ls.$(OBJEXT) popen.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@security.$(OBJEXT) gssapi.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_TRUE@gss_userok.$(OBJEXT)
+@KRB4_FALSE@@KRB5_FALSE@ftpd_OBJECTS = ftpcmd.$(OBJEXT) ftpd.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_FALSE@logwtmp.$(OBJEXT) ls.$(OBJEXT) popen.$(OBJEXT) \
+@KRB4_FALSE@@KRB5_FALSE@security.$(OBJEXT)
+@KRB4_TRUE@@KRB5_TRUE@ftpd_OBJECTS = ftpcmd.$(OBJEXT) ftpd.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@logwtmp.$(OBJEXT) ls.$(OBJEXT) popen.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@security.$(OBJEXT) krb4.$(OBJEXT) kauth.$(OBJEXT) \
+@KRB4_TRUE@@KRB5_TRUE@gssapi.$(OBJEXT) gss_userok.$(OBJEXT)
+ftpd_LDADD = $(LDADD)
+@KRB4_TRUE@@KRB5_FALSE@ftpd_DEPENDENCIES = ../common/libcommon.a \
+@KRB4_TRUE@@KRB5_FALSE@$(top_builddir)/lib/kafs/libkafs.la \
+@KRB4_TRUE@@KRB5_FALSE@$(top_builddir)/lib/des/libdes.la
+@KRB4_FALSE@@KRB5_TRUE@ftpd_DEPENDENCIES = ../common/libcommon.a \
+@KRB4_FALSE@@KRB5_TRUE@$(top_builddir)/lib/gssapi/libgssapi.la \
+@KRB4_FALSE@@KRB5_TRUE@$(top_builddir)/lib/krb5/libkrb5.la \
+@KRB4_FALSE@@KRB5_TRUE@$(top_builddir)/lib/asn1/libasn1.la \
+@KRB4_FALSE@@KRB5_TRUE@$(top_builddir)/lib/des/libdes.la
+@KRB4_FALSE@@KRB5_FALSE@ftpd_DEPENDENCIES = ../common/libcommon.a \
+@KRB4_FALSE@@KRB5_FALSE@$(top_builddir)/lib/des/libdes.la
+@KRB4_TRUE@@KRB5_TRUE@ftpd_DEPENDENCIES = ../common/libcommon.a \
+@KRB4_TRUE@@KRB5_TRUE@$(top_builddir)/lib/kafs/libkafs.la \
+@KRB4_TRUE@@KRB5_TRUE@$(top_builddir)/lib/gssapi/libgssapi.la \
+@KRB4_TRUE@@KRB5_TRUE@$(top_builddir)/lib/krb5/libkrb5.la \
+@KRB4_TRUE@@KRB5_TRUE@$(top_builddir)/lib/asn1/libasn1.la \
+@KRB4_TRUE@@KRB5_TRUE@$(top_builddir)/lib/des/libdes.la
+ftpd_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man5dir = $(mandir)/man5
+man8dir = $(mandir)/man8
+MANS = $(man_MANS)
+DIST_COMMON = Makefile.am Makefile.in ftpcmd.c
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(ftpd_SOURCES) $(EXTRA_ftpd_SOURCES)
+OBJECTS = $(ftpd_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .1 .3 .5 .8 .S .c .cat1 .cat3 .cat5 .cat8 .et .h .lo .o .obj .s .x .y
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common
+ cd $(top_srcdir) && $(AUTOMAKE) --foreign appl/ftp/ftpd/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-libexecPROGRAMS:
+
+clean-libexecPROGRAMS:
+ -test -z "$(libexec_PROGRAMS)" || rm -f $(libexec_PROGRAMS)
+
+distclean-libexecPROGRAMS:
+
+maintainer-clean-libexecPROGRAMS:
+
+install-libexecPROGRAMS: $(libexec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libexecdir)
+ @list='$(libexec_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(LIBTOOL) --mode=install $(INSTALL_PROGRAM) $$p $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-libexecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(libexec_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(libexecdir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+# FIXME: We should only use cygpath when building on Windows,
+# and only if it is available.
+.c.obj:
+ $(COMPILE) -c `cygpath -w $<`
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+ -rm -f *.$(OBJEXT)
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+.c.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.s.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+.S.lo:
+ $(LIBTOOL) --mode=compile $(COMPILE) -c $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+
+maintainer-clean-libtool:
+
+ftpd$(EXEEXT): $(ftpd_OBJECTS) $(ftpd_DEPENDENCIES)
+ @rm -f ftpd$(EXEEXT)
+ $(LINK) $(ftpd_LDFLAGS) $(ftpd_OBJECTS) $(ftpd_LDADD) $(LIBS)
+.y.c:
+ $(YACC) $(AM_YFLAGS) $(YFLAGS) $< && mv y.tab.c $*.c
+ if test -f y.tab.h; then \
+ if cmp -s y.tab.h $*.h; then rm -f y.tab.h; else mv y.tab.h $*.h; fi; \
+ else :; fi
+ftpcmd.h: ftpcmd.c
+
+
+install-man5:
+ $(mkinstalldirs) $(DESTDIR)$(man5dir)
+ @list='$(man5_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.5*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man5dir)/$$inst; \
+ done
+
+uninstall-man5:
+ @list='$(man5_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.5*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man5dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man5dir)/$$inst; \
+ done
+
+install-man8:
+ $(mkinstalldirs) $(DESTDIR)$(man8dir)
+ @list='$(man8_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
+ done
+
+uninstall-man8:
+ @list='$(man8_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man8dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man5 install-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man5 uninstall-man8
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = appl/ftp/ftpd
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-libexecPROGRAMS
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+install-exec: install-exec-am
+
+install-data-am: install-man install-data-local
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-libexecPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS) all-local
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libexecdir) $(DESTDIR)$(mandir)/man5 \
+ $(DESTDIR)$(mandir)/man8
+
+
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+ -test -z "ftpcmdhftpcmdc" || rm -f ftpcmdh ftpcmdc
+mostlyclean-am: mostlyclean-libexecPROGRAMS mostlyclean-compile \
+ mostlyclean-libtool mostlyclean-tags \
+ mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-libexecPROGRAMS clean-compile clean-libtool clean-tags \
+ clean-generic mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-libexecPROGRAMS distclean-compile \
+ distclean-libtool distclean-tags distclean-generic \
+ clean-am
+ -rm -f libtool
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-libexecPROGRAMS \
+ maintainer-clean-compile maintainer-clean-libtool \
+ maintainer-clean-tags maintainer-clean-generic \
+ distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-libexecPROGRAMS distclean-libexecPROGRAMS \
+clean-libexecPROGRAMS maintainer-clean-libexecPROGRAMS \
+uninstall-libexecPROGRAMS install-libexecPROGRAMS mostlyclean-compile \
+distclean-compile clean-compile maintainer-clean-compile \
+mostlyclean-libtool distclean-libtool clean-libtool \
+maintainer-clean-libtool install-man5 uninstall-man5 install-man8 \
+uninstall-man8 install-man uninstall-man tags mostlyclean-tags \
+distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
+dvi-am dvi check-local check check-am installcheck-am installcheck \
+install-exec-am install-exec install-data-local install-data-am \
+install-data install-am install uninstall-am uninstall all-local \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+install-suid-programs:
+ @foo='$(bin_SUIDS)'; \
+ for file in $$foo; do \
+ x=$(DESTDIR)$(bindir)/$$file; \
+ if chown 0:0 $$x && chmod u+s $$x; then :; else \
+ chmod 0 $$x; fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+ @foo='$(include_HEADERS) $(build_HEADERZ)'; \
+ for f in $$foo; do \
+ f=`basename $$f`; \
+ if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+ else file="$$f"; fi; \
+ if cmp -s $$file $(buildinclude)/$$f 2> /dev/null ; then \
+ : ; else \
+ echo " cp $$file $(buildinclude)/$$f"; \
+ cp $$file $(buildinclude)/$$f; \
+ fi ; \
+ done
+
+all-local: install-build-headers
+#NROFF_MAN = nroff -man
+.1.cat1:
+ $(NROFF_MAN) $< > $@
+.3.cat3:
+ $(NROFF_MAN) $< > $@
+.5.cat5:
+ $(NROFF_MAN) $< > $@
+.8.cat8:
+ $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+ @foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat3-mans:
+ @foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat5-mans:
+ @foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-cat8-mans:
+ @foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done ;\
+ for i in $$foo; do \
+ x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+ echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+ $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+ done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat1-mans:
+ @ext=1;\
+ foo='$(man1_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.1) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat1dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat1/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat1dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat3-mans:
+ @ext=3;\
+ foo='$(man3_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.3) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat3dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat3/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat3dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat5-mans:
+ @ext=5;\
+ foo='$(man5_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.5) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat5dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat5/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat5dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat8-mans:
+ @ext=8;\
+ foo='$(man8_MANS)'; \
+ bar='$(man_MANS)'; \
+ for i in $$bar; do \
+ case $$i in \
+ *.8) foo="$$foo $$i";; \
+ esac; done; \
+ if test "$$foo"; then \
+ $(mkinstalldirs) $(DESTDIR)$(cat8dir); \
+ for x in $$foo; do \
+ f=`echo $$x | sed 's/\.[^.]*$$/.cat8/'`; \
+ if test -f "$(srcdir)/$$f"; then \
+ b=`echo $$x | sed 's!$(MANRX)!\1!'`; \
+ echo "$(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX)";\
+ $(INSTALL_DATA) $(srcdir)/$$g $(DESTDIR)$(cat8dir)/$$b.$(CATSUFFIX);\
+ fi; \
+ done ;\
+ fi
+
+install-cat-mans: install-cat1-mans install-cat3-mans install-cat5-mans install-cat8-mans
+
+install-data-local: install-cat-mans
+
+.et.h:
+ $(COMPILE_ET) $<
+.et.c:
+ $(COMPILE_ET) $<
+
+.x.c:
+ @cmp -s $< $@ 2> /dev/null || cp $< $@
+
+check-local::
+ @foo='$(CHECK_LOCAL)'; \
+ if test "$$foo"; then \
+ failed=0; all=0; \
+ for i in $$foo; do \
+ all=`expr $$all + 1`; \
+ if ./$$i --version > /dev/null 2>&1; then \
+ echo "PASS: $$i"; \
+ else \
+ echo "FAIL: $$i"; \
+ failed=`expr $$failed + 1`; \
+ fi; \
+ done; \
+ if test "$$failed" -eq 0; then \
+ banner="All $$all tests passed"; \
+ else \
+ banner="$$failed of $$all tests failed"; \
+ fi; \
+ dashes=`echo "$$banner" | sed s/./=/g`; \
+ echo "$$dashes"; \
+ echo "$$banner"; \
+ echo "$$dashes"; \
+ test "$$failed" -eq 0; \
+ fi
+
+$(ftpd_OBJECTS): security.h
+
+security.c:
+ @test -f security.c || $(LN_S) $(srcdir)/../ftp/security.c .
+security.h:
+ @test -f security.h || $(LN_S) $(srcdir)/../ftp/security.h .
+krb4.c:
+ @test -f krb4.c || $(LN_S) $(srcdir)/../ftp/krb4.c .
+gssapi.c:
+ @test -f gssapi.c || $(LN_S) $(srcdir)/../ftp/gssapi.c .
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/crypto/heimdal/appl/ftp/ftpd/extern.h b/crypto/heimdal/appl/ftp/ftpd/extern.h
new file mode 100644
index 0000000..2e1e0d0
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/extern.h
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * 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.
+ *
+ * @(#)extern.h 8.2 (Berkeley) 4/4/94
+ */
+
+#ifndef _EXTERN_H_
+#define _EXTERN_H_
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef NBBY
+#define NBBY CHAR_BIT
+#endif
+
+void abor(void);
+void blkfree(char **);
+char **copyblk(char **);
+void cwd(char *);
+void do_delete(char *);
+void dologout(int);
+void eprt(char *);
+void epsv(char *);
+void fatal(char *);
+int filename_check(char *);
+int ftpd_pclose(FILE *);
+FILE *ftpd_popen(char *, char *, int, int);
+char *ftpd_getline(char *, int);
+void ftpd_logwtmp(char *, char *, char *);
+void lreply(int, const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void makedir(char *);
+void nack(char *);
+void nreply(const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+void pass(char *);
+void pasv(void);
+void perror_reply(int, const char *);
+void pwd(void);
+void removedir(char *);
+void renamecmd(char *, char *);
+char *renamefrom(char *);
+void reply(int, const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 2, 3)))
+#endif
+;
+void retrieve(const char *, char *);
+void send_file_list(char *);
+void setproctitle(const char *, ...)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 1, 2)))
+#endif
+;
+void statcmd(void);
+void statfilecmd(char *);
+void do_store(char *, char *, int);
+void upper(char *);
+void user(char *);
+void yyerror(char *);
+
+void list_file(char*);
+
+void kauth(char *, char*);
+void klist(void);
+void cond_kdestroy(void);
+void kdestroy(void);
+void krbtkfile(const char *tkfile);
+void afslog(const char *cell);
+void afsunlog(void);
+
+int find(char *);
+
+void builtin_ls(FILE*, const char*);
+
+int do_login(int code, char *passwd);
+int klogin(char *name, char *password);
+
+const char *ftp_rooted(const char *path);
+
+extern struct sockaddr *ctrl_addr, *his_addr;
+extern char hostname[];
+
+extern struct sockaddr *data_dest;
+extern int logged_in;
+extern struct passwd *pw;
+extern int guest;
+extern int logging;
+extern int type;
+extern int oobflag;
+extern off_t file_size;
+extern off_t byte_count;
+extern jmp_buf urgcatch;
+
+extern int form;
+extern int debug;
+extern int ftpd_timeout;
+extern int maxtimeout;
+extern int pdata;
+extern char hostname[], remotehost[];
+extern char proctitle[];
+extern int usedefault;
+extern int transflag;
+extern char tmpline[];
+
+#endif /* _EXTERN_H_ */
diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y
new file mode 100644
index 0000000..07ff9a5
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ftpcmd.y
@@ -0,0 +1,1455 @@
+/* $NetBSD: ftpcmd.y,v 1.6 1995/06/03 22:46:45 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1985, 1988, 1993, 1994
+ * 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.
+ *
+ * @(#)ftpcmd.y 8.3 (Berkeley) 4/6/94
+ */
+
+/*
+ * Grammar for FTP commands.
+ * See RFC 959.
+ */
+
+%{
+
+#include "ftpd_locl.h"
+RCSID("$Id: ftpcmd.y,v 1.56 1999/10/26 11:56:23 assar Exp $");
+
+off_t restart_point;
+
+static int cmd_type;
+static int cmd_form;
+static int cmd_bytesz;
+char cbuf[2048];
+char *fromname;
+
+struct tab {
+ char *name;
+ short token;
+ short state;
+ short implemented; /* 1 if command is implemented */
+ char *help;
+};
+
+extern struct tab cmdtab[];
+extern struct tab sitetab[];
+
+static char *copy (char *);
+static void help (struct tab *, char *);
+static struct tab *
+ lookup (struct tab *, char *);
+static void sizecmd (char *);
+static RETSIGTYPE toolong (int);
+static int yylex (void);
+
+/* This is for bison */
+
+#if !defined(alloca) && !defined(HAVE_ALLOCA)
+#define alloca(x) malloc(x)
+#endif
+
+%}
+
+%union {
+ int i;
+ char *s;
+}
+
+%token
+ A B C E F I
+ L N P R S T
+
+ SP CRLF COMMA
+
+ USER PASS ACCT REIN QUIT PORT
+ PASV TYPE STRU MODE RETR STOR
+ APPE MLFL MAIL MSND MSOM MSAM
+ MRSQ MRCP ALLO REST RNFR RNTO
+ ABOR DELE CWD LIST NLST SITE
+ sTAT HELP NOOP MKD RMD PWD
+ CDUP STOU SMNT SYST SIZE MDTM
+ EPRT EPSV
+
+ UMASK IDLE CHMOD
+
+ AUTH ADAT PROT PBSZ CCC MIC
+ CONF ENC
+
+ KAUTH KLIST KDESTROY KRBTKFILE AFSLOG
+ LOCATE URL
+
+ FEAT OPTS
+
+ LEXERR
+
+%token <s> STRING
+%token <i> NUMBER
+
+%type <i> check_login check_login_no_guest check_secure octal_number byte_size
+%type <i> struct_code mode_code type_code form_code
+%type <s> pathstring pathname password username
+
+%start cmd_list
+
+%%
+
+cmd_list
+ : /* empty */
+ | cmd_list cmd
+ {
+ fromname = (char *) 0;
+ restart_point = (off_t) 0;
+ }
+ | cmd_list rcmd
+ ;
+
+cmd
+ : USER SP username CRLF
+ {
+ user($3);
+ free($3);
+ }
+ | PASS SP password CRLF
+ {
+ pass($3);
+ memset ($3, 0, strlen($3));
+ free($3);
+ }
+ | PORT SP host_port CRLF
+ {
+ usedefault = 0;
+ if (pdata >= 0) {
+ close(pdata);
+ pdata = -1;
+ }
+ reply(200, "PORT command successful.");
+ }
+ | EPRT SP STRING CRLF
+ {
+ eprt ($3);
+ free ($3);
+ }
+ | PASV CRLF
+ {
+ pasv ();
+ }
+ | EPSV CRLF
+ {
+ epsv (NULL);
+ }
+ | EPSV SP STRING CRLF
+ {
+ epsv ($3);
+ free ($3);
+ }
+ | TYPE SP type_code CRLF
+ {
+ switch (cmd_type) {
+
+ case TYPE_A:
+ if (cmd_form == FORM_N) {
+ reply(200, "Type set to A.");
+ type = cmd_type;
+ form = cmd_form;
+ } else
+ reply(504, "Form must be N.");
+ break;
+
+ case TYPE_E:
+ reply(504, "Type E not implemented.");
+ break;
+
+ case TYPE_I:
+ reply(200, "Type set to I.");
+ type = cmd_type;
+ break;
+
+ case TYPE_L:
+#if NBBY == 8
+ if (cmd_bytesz == 8) {
+ reply(200,
+ "Type set to L (byte size 8).");
+ type = cmd_type;
+ } else
+ reply(504, "Byte size must be 8.");
+#else /* NBBY == 8 */
+ UNIMPLEMENTED for NBBY != 8
+#endif /* NBBY == 8 */
+ }
+ }
+ | STRU SP struct_code CRLF
+ {
+ switch ($3) {
+
+ case STRU_F:
+ reply(200, "STRU F ok.");
+ break;
+
+ default:
+ reply(504, "Unimplemented STRU type.");
+ }
+ }
+ | MODE SP mode_code CRLF
+ {
+ switch ($3) {
+
+ case MODE_S:
+ reply(200, "MODE S ok.");
+ break;
+
+ default:
+ reply(502, "Unimplemented MODE type.");
+ }
+ }
+ | ALLO SP NUMBER CRLF
+ {
+ reply(202, "ALLO command ignored.");
+ }
+ | ALLO SP NUMBER SP R SP NUMBER CRLF
+ {
+ reply(202, "ALLO command ignored.");
+ }
+ | RETR SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ retrieve(0, name);
+ if (name != NULL)
+ free(name);
+ }
+ | STOR SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ do_store(name, "w", 0);
+ if (name != NULL)
+ free(name);
+ }
+ | APPE SP pathname CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ do_store(name, "a", 0);
+ if (name != NULL)
+ free(name);
+ }
+ | NLST CRLF check_login
+ {
+ if ($3)
+ send_file_list(".");
+ }
+ | NLST SP STRING CRLF check_login
+ {
+ char *name = $3;
+
+ if ($5 && name != NULL)
+ send_file_list(name);
+ if (name != NULL)
+ free(name);
+ }
+ | LIST CRLF check_login
+ {
+ if($3)
+ list_file(".");
+ }
+ | LIST SP pathname CRLF check_login
+ {
+ if($5)
+ list_file($3);
+ free($3);
+ }
+ | sTAT SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ statfilecmd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | sTAT CRLF
+ {
+ if(oobflag){
+ if (file_size != (off_t) -1)
+ reply(213, "Status: %lu of %lu bytes transferred",
+ (unsigned long)byte_count,
+ (unsigned long)file_size);
+ else
+ reply(213, "Status: %lu bytes transferred",
+ (unsigned long)byte_count);
+ }else
+ statcmd();
+ }
+ | DELE SP pathname CRLF check_login_no_guest
+ {
+ if ($5 && $3 != NULL)
+ do_delete($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | RNTO SP pathname CRLF check_login_no_guest
+ {
+ if($5){
+ if (fromname) {
+ renamecmd(fromname, $3);
+ free(fromname);
+ fromname = (char *) 0;
+ } else {
+ reply(503, "Bad sequence of commands.");
+ }
+ }
+ if ($3 != NULL)
+ free($3);
+ }
+ | ABOR CRLF
+ {
+ if(oobflag){
+ reply(426, "Transfer aborted. Data connection closed.");
+ reply(226, "Abort successful");
+ oobflag = 0;
+ longjmp(urgcatch, 1);
+ }else
+ reply(225, "ABOR command successful.");
+ }
+ | CWD CRLF check_login
+ {
+ if ($3)
+ cwd(pw->pw_dir);
+ }
+ | CWD SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ cwd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | HELP CRLF
+ {
+ help(cmdtab, (char *) 0);
+ }
+ | HELP SP STRING CRLF
+ {
+ char *cp = $3;
+
+ if (strncasecmp(cp, "SITE", 4) == 0) {
+ cp = $3 + 4;
+ if (*cp == ' ')
+ cp++;
+ if (*cp)
+ help(sitetab, cp);
+ else
+ help(sitetab, (char *) 0);
+ } else
+ help(cmdtab, $3);
+ }
+ | NOOP CRLF
+ {
+ reply(200, "NOOP command successful.");
+ }
+ | MKD SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ makedir($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | RMD SP pathname CRLF check_login_no_guest
+ {
+ if ($5 && $3 != NULL)
+ removedir($3);
+ if ($3 != NULL)
+ free($3);
+ }
+ | PWD CRLF check_login
+ {
+ if ($3)
+ pwd();
+ }
+ | CDUP CRLF check_login
+ {
+ if ($3)
+ cwd("..");
+ }
+ | FEAT CRLF
+ {
+ lreply(211, "Supported features:");
+ lreply(0, " MDTM");
+ lreply(0, " REST STREAM");
+ lreply(0, " SIZE");
+ reply(211, "End");
+ }
+ | OPTS SP STRING CRLF
+ {
+ free ($3);
+ reply(501, "Bad options");
+ }
+
+ | SITE SP HELP CRLF
+ {
+ help(sitetab, (char *) 0);
+ }
+ | SITE SP HELP SP STRING CRLF
+ {
+ help(sitetab, $5);
+ }
+ | SITE SP UMASK CRLF check_login
+ {
+ if ($5) {
+ int oldmask = umask(0);
+ umask(oldmask);
+ reply(200, "Current UMASK is %03o", oldmask);
+ }
+ }
+ | SITE SP UMASK SP octal_number CRLF check_login_no_guest
+ {
+ if ($7) {
+ if (($5 == -1) || ($5 > 0777)) {
+ reply(501, "Bad UMASK value");
+ } else {
+ int oldmask = umask($5);
+ reply(200,
+ "UMASK set to %03o (was %03o)",
+ $5, oldmask);
+ }
+ }
+ }
+ | SITE SP CHMOD SP octal_number SP pathname CRLF check_login_no_guest
+ {
+ if ($9 && $7 != NULL) {
+ if ($5 > 0777)
+ reply(501,
+ "CHMOD: Mode value must be between 0 and 0777");
+ else if (chmod($7, $5) < 0)
+ perror_reply(550, $7);
+ else
+ reply(200, "CHMOD command successful.");
+ }
+ if ($7 != NULL)
+ free($7);
+ }
+ | SITE SP IDLE CRLF
+ {
+ reply(200,
+ "Current IDLE time limit is %d seconds; max %d",
+ ftpd_timeout, maxtimeout);
+ }
+ | SITE SP IDLE SP NUMBER CRLF
+ {
+ if ($5 < 30 || $5 > maxtimeout) {
+ reply(501,
+ "Maximum IDLE time must be between 30 and %d seconds",
+ maxtimeout);
+ } else {
+ ftpd_timeout = $5;
+ alarm((unsigned) ftpd_timeout);
+ reply(200,
+ "Maximum IDLE time set to %d seconds",
+ ftpd_timeout);
+ }
+ }
+
+ | SITE SP KAUTH SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ char *p;
+
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else{
+ if($7 && $5 != NULL){
+ p = strpbrk($5, " \t");
+ if(p){
+ *p++ = 0;
+ kauth($5, p + strspn(p, " \t"));
+ }else
+ kauth($5, NULL);
+ }
+ }
+ if($5 != NULL)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KLIST CRLF check_login
+ {
+#ifdef KRB4
+ if($5)
+ klist();
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KDESTROY CRLF check_login
+ {
+#ifdef KRB4
+ if($5)
+ kdestroy();
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP KRBTKFILE SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($7 && $5)
+ krbtkfile($5);
+ if($5)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP AFSLOG CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($5)
+ afslog(NULL);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP AFSLOG SP STRING CRLF check_login
+ {
+#ifdef KRB4
+ if(guest)
+ reply(500, "Can't be done as guest.");
+ else if($7)
+ afslog($5);
+ if($5)
+ free($5);
+#else
+ reply(500, "Command not implemented.");
+#endif
+ }
+ | SITE SP LOCATE SP STRING CRLF check_login
+ {
+ if($7 && $5 != NULL)
+ find($5);
+ if($5 != NULL)
+ free($5);
+ }
+ | SITE SP URL CRLF
+ {
+ reply(200, "http://www.pdc.kth.se/kth-krb/");
+ }
+ | STOU SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ do_store($3, "w", 1);
+ if ($3 != NULL)
+ free($3);
+ }
+ | SYST CRLF
+ {
+#if defined(unix) || defined(__unix__) || defined(__unix) || defined(_AIX) || defined(_CRAY)
+ reply(215, "UNIX Type: L%d", NBBY);
+#else
+ reply(215, "UNKNOWN Type: L%d", NBBY);
+#endif
+ }
+
+ /*
+ * SIZE is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return size of file in a format suitable for
+ * using with RESTART (we just count bytes).
+ */
+ | SIZE SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL)
+ sizecmd($3);
+ if ($3 != NULL)
+ free($3);
+ }
+
+ /*
+ * MDTM is not in RFC959, but Postel has blessed it and
+ * it will be in the updated RFC.
+ *
+ * Return modification time of file as an ISO 3307
+ * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx
+ * where xxx is the fractional second (of any precision,
+ * not necessarily 3 digits)
+ */
+ | MDTM SP pathname CRLF check_login
+ {
+ if ($5 && $3 != NULL) {
+ struct stat stbuf;
+ if (stat($3, &stbuf) < 0)
+ reply(550, "%s: %s",
+ $3, strerror(errno));
+ else if (!S_ISREG(stbuf.st_mode)) {
+ reply(550,
+ "%s: not a plain file.", $3);
+ } else {
+ struct tm *t;
+ t = gmtime(&stbuf.st_mtime);
+ reply(213,
+ "%04d%02d%02d%02d%02d%02d",
+ t->tm_year + 1900,
+ t->tm_mon + 1,
+ t->tm_mday,
+ t->tm_hour,
+ t->tm_min,
+ t->tm_sec);
+ }
+ }
+ if ($3 != NULL)
+ free($3);
+ }
+ | QUIT CRLF
+ {
+ reply(221, "Goodbye.");
+ dologout(0);
+ }
+ | error CRLF
+ {
+ yyerrok;
+ }
+ ;
+rcmd
+ : RNFR SP pathname CRLF check_login_no_guest
+ {
+ restart_point = (off_t) 0;
+ if ($5 && $3) {
+ fromname = renamefrom($3);
+ if (fromname == (char *) 0 && $3) {
+ free($3);
+ }
+ }
+ }
+ | REST SP byte_size CRLF
+ {
+ fromname = (char *) 0;
+ restart_point = $3; /* XXX $3 is only "int" */
+ reply(350, "Restarting at %ld. %s",
+ (long)restart_point,
+ "Send STORE or RETRIEVE to initiate transfer.");
+ }
+ | AUTH SP STRING CRLF
+ {
+ auth($3);
+ free($3);
+ }
+ | ADAT SP STRING CRLF
+ {
+ adat($3);
+ free($3);
+ }
+ | PBSZ SP NUMBER CRLF
+ {
+ pbsz($3);
+ }
+ | PROT SP STRING CRLF
+ {
+ prot($3);
+ }
+ | CCC CRLF
+ {
+ ccc();
+ }
+ | MIC SP STRING CRLF
+ {
+ mec($3, prot_safe);
+ free($3);
+ }
+ | CONF SP STRING CRLF
+ {
+ mec($3, prot_confidential);
+ free($3);
+ }
+ | ENC SP STRING CRLF
+ {
+ mec($3, prot_private);
+ free($3);
+ }
+ ;
+
+username
+ : STRING
+ ;
+
+password
+ : /* empty */
+ {
+ $$ = (char *)calloc(1, sizeof(char));
+ }
+ | STRING
+ ;
+
+byte_size
+ : NUMBER
+ ;
+
+host_port
+ : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA
+ NUMBER COMMA NUMBER
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)data_dest;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons($9 * 256 + $11);
+ sin->sin_addr.s_addr =
+ htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7);
+ }
+ ;
+
+form_code
+ : N
+ {
+ $$ = FORM_N;
+ }
+ | T
+ {
+ $$ = FORM_T;
+ }
+ | C
+ {
+ $$ = FORM_C;
+ }
+ ;
+
+type_code
+ : A
+ {
+ cmd_type = TYPE_A;
+ cmd_form = FORM_N;
+ }
+ | A SP form_code
+ {
+ cmd_type = TYPE_A;
+ cmd_form = $3;
+ }
+ | E
+ {
+ cmd_type = TYPE_E;
+ cmd_form = FORM_N;
+ }
+ | E SP form_code
+ {
+ cmd_type = TYPE_E;
+ cmd_form = $3;
+ }
+ | I
+ {
+ cmd_type = TYPE_I;
+ }
+ | L
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = NBBY;
+ }
+ | L SP byte_size
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $3;
+ }
+ /* this is for a bug in the BBN ftp */
+ | L byte_size
+ {
+ cmd_type = TYPE_L;
+ cmd_bytesz = $2;
+ }
+ ;
+
+struct_code
+ : F
+ {
+ $$ = STRU_F;
+ }
+ | R
+ {
+ $$ = STRU_R;
+ }
+ | P
+ {
+ $$ = STRU_P;
+ }
+ ;
+
+mode_code
+ : S
+ {
+ $$ = MODE_S;
+ }
+ | B
+ {
+ $$ = MODE_B;
+ }
+ | C
+ {
+ $$ = MODE_C;
+ }
+ ;
+
+pathname
+ : pathstring
+ {
+ /*
+ * Problem: this production is used for all pathname
+ * processing, but only gives a 550 error reply.
+ * This is a valid reply in some cases but not in others.
+ */
+ if (logged_in && $1 && *$1 == '~') {
+ glob_t gl;
+ int flags =
+ GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ if (glob($1, flags, NULL, &gl) ||
+ gl.gl_pathc == 0) {
+ reply(550, "not found");
+ $$ = NULL;
+ } else {
+ $$ = strdup(gl.gl_pathv[0]);
+ }
+ globfree(&gl);
+ free($1);
+ } else
+ $$ = $1;
+ }
+ ;
+
+pathstring
+ : STRING
+ ;
+
+octal_number
+ : NUMBER
+ {
+ int ret, dec, multby, digit;
+
+ /*
+ * Convert a number that was read as decimal number
+ * to what it would be if it had been read as octal.
+ */
+ dec = $1;
+ multby = 1;
+ ret = 0;
+ while (dec) {
+ digit = dec%10;
+ if (digit > 7) {
+ ret = -1;
+ break;
+ }
+ ret += digit * multby;
+ multby *= 8;
+ dec /= 10;
+ }
+ $$ = ret;
+ }
+ ;
+
+
+check_login_no_guest : check_login
+ {
+ $$ = $1 && !guest;
+ if($1 && !$$)
+ reply(550, "Permission denied");
+ }
+ ;
+
+check_login : check_secure
+ {
+ if($1) {
+ if(($$ = logged_in) == 0)
+ reply(530, "Please login with USER and PASS.");
+ } else
+ $$ = 0;
+ }
+ ;
+
+check_secure : /* empty */
+ {
+ $$ = 1;
+ if(sec_complete && !secure_command()) {
+ $$ = 0;
+ reply(533, "Command protection level denied "
+ "for paranoid reasons.");
+ }
+ }
+ ;
+
+%%
+
+extern jmp_buf errcatch;
+
+#define CMD 0 /* beginning of command */
+#define ARGS 1 /* expect miscellaneous arguments */
+#define STR1 2 /* expect SP followed by STRING */
+#define STR2 3 /* expect STRING */
+#define OSTR 4 /* optional SP then STRING */
+#define ZSTR1 5 /* SP then optional STRING */
+#define ZSTR2 6 /* optional STRING after SP */
+#define SITECMD 7 /* SITE command */
+#define NSTR 8 /* Number followed by a string */
+
+struct tab cmdtab[] = { /* In order defined in RFC 765 */
+ { "USER", USER, STR1, 1, "<sp> username" },
+ { "PASS", PASS, ZSTR1, 1, "<sp> password" },
+ { "ACCT", ACCT, STR1, 0, "(specify account)" },
+ { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
+ { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
+ { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
+ { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
+ { "EPRT", EPRT, STR1, 1, "<sp> string" },
+ { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
+ { "EPSV", EPSV, OSTR, 1, "[<sp> foo]" },
+ { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
+ { "STRU", STRU, ARGS, 1, "(specify file structure)" },
+ { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
+ { "RETR", RETR, STR1, 1, "<sp> file-name" },
+ { "STOR", STOR, STR1, 1, "<sp> file-name" },
+ { "APPE", APPE, STR1, 1, "<sp> file-name" },
+ { "MLFL", MLFL, OSTR, 0, "(mail file)" },
+ { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
+ { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
+ { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
+ { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
+ { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
+ { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
+ { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
+ { "REST", REST, ARGS, 1, "<sp> offset (restart command)" },
+ { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
+ { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
+ { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
+ { "DELE", DELE, STR1, 1, "<sp> file-name" },
+ { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
+ { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
+ { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
+ { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
+ { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
+ { "STAT", sTAT, OSTR, 1, "[ <sp> path-name ]" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+ { "NOOP", NOOP, ARGS, 1, "" },
+ { "MKD", MKD, STR1, 1, "<sp> path-name" },
+ { "XMKD", MKD, STR1, 1, "<sp> path-name" },
+ { "RMD", RMD, STR1, 1, "<sp> path-name" },
+ { "XRMD", RMD, STR1, 1, "<sp> path-name" },
+ { "PWD", PWD, ARGS, 1, "(return current directory)" },
+ { "XPWD", PWD, ARGS, 1, "(return current directory)" },
+ { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
+ { "STOU", STOU, STR1, 1, "<sp> file-name" },
+ { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
+ { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
+
+ /* extensions from RFC2228 */
+ { "AUTH", AUTH, STR1, 1, "<sp> auth-type" },
+ { "ADAT", ADAT, STR1, 1, "<sp> auth-data" },
+ { "PBSZ", PBSZ, ARGS, 1, "<sp> buffer-size" },
+ { "PROT", PROT, STR1, 1, "<sp> prot-level" },
+ { "CCC", CCC, ARGS, 1, "" },
+ { "MIC", MIC, STR1, 1, "<sp> integrity command" },
+ { "CONF", CONF, STR1, 1, "<sp> confidentiality command" },
+ { "ENC", ENC, STR1, 1, "<sp> privacy command" },
+
+ /* RFC2389 */
+ { "FEAT", FEAT, ARGS, 1, "" },
+ { "OPTS", OPTS, ARGS, 1, "<sp> command [<sp> options]" },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+struct tab sitetab[] = {
+ { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
+ { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
+ { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
+ { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
+
+ { "KAUTH", KAUTH, STR1, 1, "<sp> principal [ <sp> ticket ]" },
+ { "KLIST", KLIST, ARGS, 1, "(show ticket file)" },
+ { "KDESTROY", KDESTROY, ARGS, 1, "(destroy tickets)" },
+ { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" },
+ { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" },
+
+ { "LOCATE", LOCATE, STR1, 1, "<sp> globexpr" },
+ { "FIND", LOCATE, STR1, 1, "<sp> globexpr" },
+
+ { "URL", URL, ARGS, 1, "?" },
+
+ { NULL, 0, 0, 0, 0 }
+};
+
+static struct tab *
+lookup(struct tab *p, char *cmd)
+{
+
+ for (; p->name != NULL; p++)
+ if (strcmp(cmd, p->name) == 0)
+ return (p);
+ return (0);
+}
+
+/*
+ * ftpd_getline - a hacked up version of fgets to ignore TELNET escape codes.
+ */
+char *
+ftpd_getline(char *s, int n)
+{
+ int c;
+ char *cs;
+
+ cs = s;
+/* tmpline may contain saved command from urgent mode interruption */
+ if(ftp_command){
+ strlcpy(s, ftp_command, n);
+ if (debug)
+ syslog(LOG_DEBUG, "command: %s", s);
+#ifdef XXX
+ fprintf(stderr, "%s\n", s);
+#endif
+ return s;
+ }
+ while ((c = getc(stdin)) != EOF) {
+ c &= 0377;
+ if (c == IAC) {
+ if ((c = getc(stdin)) != EOF) {
+ c &= 0377;
+ switch (c) {
+ case WILL:
+ case WONT:
+ c = getc(stdin);
+ printf("%c%c%c", IAC, DONT, 0377&c);
+ fflush(stdout);
+ continue;
+ case DO:
+ case DONT:
+ c = getc(stdin);
+ printf("%c%c%c", IAC, WONT, 0377&c);
+ fflush(stdout);
+ continue;
+ case IAC:
+ break;
+ default:
+ continue; /* ignore command */
+ }
+ }
+ }
+ *cs++ = c;
+ if (--n <= 0 || c == '\n')
+ break;
+ }
+ if (c == EOF && cs == s)
+ return (NULL);
+ *cs++ = '\0';
+ if (debug) {
+ if (!guest && strncasecmp("pass ", s, 5) == 0) {
+ /* Don't syslog passwords */
+ syslog(LOG_DEBUG, "command: %.5s ???", s);
+ } else {
+ char *cp;
+ int len;
+
+ /* Don't syslog trailing CR-LF */
+ len = strlen(s);
+ cp = s + len - 1;
+ while (cp >= s && (*cp == '\n' || *cp == '\r')) {
+ --cp;
+ --len;
+ }
+ syslog(LOG_DEBUG, "command: %.*s", len, s);
+ }
+ }
+#ifdef XXX
+ fprintf(stderr, "%s\n", s);
+#endif
+ return (s);
+}
+
+static RETSIGTYPE
+toolong(int signo)
+{
+
+ reply(421,
+ "Timeout (%d seconds): closing control connection.",
+ ftpd_timeout);
+ if (logging)
+ syslog(LOG_INFO, "User %s timed out after %d seconds",
+ (pw ? pw -> pw_name : "unknown"), ftpd_timeout);
+ dologout(1);
+ SIGRETURN(0);
+}
+
+static int
+yylex(void)
+{
+ static int cpos, state;
+ char *cp, *cp2;
+ struct tab *p;
+ int n;
+ char c;
+
+ for (;;) {
+ switch (state) {
+
+ case CMD:
+ signal(SIGALRM, toolong);
+ alarm((unsigned) ftpd_timeout);
+ if (ftpd_getline(cbuf, sizeof(cbuf)-1) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ alarm(0);
+#ifdef HAVE_SETPROCTITLE
+ if (strncasecmp(cbuf, "PASS", 4) != NULL)
+ setproctitle("%s: %s", proctitle, cbuf);
+#endif /* HAVE_SETPROCTITLE */
+ if ((cp = strchr(cbuf, '\r'))) {
+ *cp++ = '\n';
+ *cp = '\0';
+ }
+ if ((cp = strpbrk(cbuf, " \n")))
+ cpos = cp - cbuf;
+ if (cpos == 0)
+ cpos = 4;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ strupr(cbuf);
+ p = lookup(cmdtab, cbuf);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ yylval.s = p->name;
+ return (p->token);
+ }
+ break;
+
+ case SITECMD:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ cp = &cbuf[cpos];
+ if ((cp2 = strpbrk(cp, " \n")))
+ cpos = cp2 - cbuf;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ strupr(cp);
+ p = lookup(sitetab, cp);
+ cbuf[cpos] = c;
+ if (p != 0) {
+ if (p->implemented == 0) {
+ state = CMD;
+ nack(p->name);
+ longjmp(errcatch,0);
+ /* NOTREACHED */
+ }
+ state = p->state;
+ yylval.s = p->name;
+ return (p->token);
+ }
+ state = CMD;
+ break;
+
+ case OSTR:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR1:
+ case ZSTR1:
+ dostr1:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ if(state == OSTR)
+ state = STR2;
+ else
+ state++;
+ return (SP);
+ }
+ break;
+
+ case ZSTR2:
+ if (cbuf[cpos] == '\n') {
+ state = CMD;
+ return (CRLF);
+ }
+ /* FALLTHROUGH */
+
+ case STR2:
+ cp = &cbuf[cpos];
+ n = strlen(cp);
+ cpos += n - 1;
+ /*
+ * Make sure the string is nonempty and \n terminated.
+ */
+ if (n > 1 && cbuf[cpos] == '\n') {
+ cbuf[cpos] = '\0';
+ yylval.s = copy(cp);
+ cbuf[cpos] = '\n';
+ state = ARGS;
+ return (STRING);
+ }
+ break;
+
+ case NSTR:
+ if (cbuf[cpos] == ' ') {
+ cpos++;
+ return (SP);
+ }
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval.i = atoi(cp);
+ cbuf[cpos] = c;
+ state = STR1;
+ return (NUMBER);
+ }
+ state = STR1;
+ goto dostr1;
+
+ case ARGS:
+ if (isdigit(cbuf[cpos])) {
+ cp = &cbuf[cpos];
+ while (isdigit(cbuf[++cpos]))
+ ;
+ c = cbuf[cpos];
+ cbuf[cpos] = '\0';
+ yylval.i = atoi(cp);
+ cbuf[cpos] = c;
+ return (NUMBER);
+ }
+ switch (cbuf[cpos++]) {
+
+ case '\n':
+ state = CMD;
+ return (CRLF);
+
+ case ' ':
+ return (SP);
+
+ case ',':
+ return (COMMA);
+
+ case 'A':
+ case 'a':
+ return (A);
+
+ case 'B':
+ case 'b':
+ return (B);
+
+ case 'C':
+ case 'c':
+ return (C);
+
+ case 'E':
+ case 'e':
+ return (E);
+
+ case 'F':
+ case 'f':
+ return (F);
+
+ case 'I':
+ case 'i':
+ return (I);
+
+ case 'L':
+ case 'l':
+ return (L);
+
+ case 'N':
+ case 'n':
+ return (N);
+
+ case 'P':
+ case 'p':
+ return (P);
+
+ case 'R':
+ case 'r':
+ return (R);
+
+ case 'S':
+ case 's':
+ return (S);
+
+ case 'T':
+ case 't':
+ return (T);
+
+ }
+ break;
+
+ default:
+ fatal("Unknown state in scanner.");
+ }
+ yyerror((char *) 0);
+ state = CMD;
+ longjmp(errcatch,0);
+ }
+}
+
+static char *
+copy(char *s)
+{
+ char *p;
+
+ p = strdup(s);
+ if (p == NULL)
+ fatal("Ran out of memory.");
+ return p;
+}
+
+static void
+help(struct tab *ctab, char *s)
+{
+ struct tab *c;
+ int width, NCMDS;
+ char *type;
+ char buf[1024];
+
+ if (ctab == sitetab)
+ type = "SITE ";
+ else
+ type = "";
+ width = 0, NCMDS = 0;
+ for (c = ctab; c->name != NULL; c++) {
+ int len = strlen(c->name);
+
+ if (len > width)
+ width = len;
+ NCMDS++;
+ }
+ width = (width + 8) &~ 7;
+ if (s == 0) {
+ int i, j, w;
+ int columns, lines;
+
+ lreply(214, "The following %scommands are recognized %s.",
+ type, "(* =>'s unimplemented)");
+ columns = 76 / width;
+ if (columns == 0)
+ columns = 1;
+ lines = (NCMDS + columns - 1) / columns;
+ for (i = 0; i < lines; i++) {
+ strlcpy (buf, " ", sizeof(buf));
+ for (j = 0; j < columns; j++) {
+ c = ctab + j * lines + i;
+ snprintf (buf + strlen(buf),
+ sizeof(buf) - strlen(buf),
+ "%s%c",
+ c->name,
+ c->implemented ? ' ' : '*');
+ if (c + lines >= &ctab[NCMDS])
+ break;
+ w = strlen(c->name) + 1;
+ while (w < width) {
+ strlcat (buf,
+ " ",
+ sizeof(buf));
+ w++;
+ }
+ }
+ lreply(214, "%s", buf);
+ }
+ reply(214, "Direct comments to kth-krb-bugs@pdc.kth.se");
+ return;
+ }
+ strupr(s);
+ c = lookup(ctab, s);
+ if (c == (struct tab *)0) {
+ reply(502, "Unknown command %s.", s);
+ return;
+ }
+ if (c->implemented)
+ reply(214, "Syntax: %s%s %s", type, c->name, c->help);
+ else
+ reply(214, "%s%-*s\t%s; unimplemented.", type, width,
+ c->name, c->help);
+}
+
+static void
+sizecmd(char *filename)
+{
+ switch (type) {
+ case TYPE_L:
+ case TYPE_I: {
+ struct stat stbuf;
+ if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
+ reply(550, "%s: not a plain file.", filename);
+ else
+ reply(213, "%lu", (unsigned long)stbuf.st_size);
+ break;
+ }
+ case TYPE_A: {
+ FILE *fin;
+ int c;
+ size_t count;
+ struct stat stbuf;
+ fin = fopen(filename, "r");
+ if (fin == NULL) {
+ perror_reply(550, filename);
+ return;
+ }
+ if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
+ reply(550, "%s: not a plain file.", filename);
+ fclose(fin);
+ return;
+ }
+
+ count = 0;
+ while((c=getc(fin)) != EOF) {
+ if (c == '\n') /* will get expanded to \r\n */
+ count++;
+ count++;
+ }
+ fclose(fin);
+
+ reply(213, "%lu", (unsigned long)count);
+ break;
+ }
+ default:
+ reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
+ }
+}
diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd.8 b/crypto/heimdal/appl/ftp/ftpd/ftpd.8
new file mode 100644
index 0000000..c51de1c
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ftpd.8
@@ -0,0 +1,473 @@
+.\" $NetBSD: ftpd.8,v 1.7 1995/04/11 02:44:53 cgd Exp $
+.\"
+.\" Copyright (c) 1985, 1988, 1991, 1993
+.\" 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.
+.\"
+.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1997
+.Dt FTPD 8
+.Os BSD 4.2
+.Sh NAME
+.Nm ftpd
+.Nd
+Internet File Transfer Protocol server
+.Sh SYNOPSIS
+.Nm ftpd
+.Op Fl a Ar authmode
+.Op Fl dilv
+.Op Fl g Ar umask
+.Op Fl p Ar port
+.Op Fl T Ar maxtimeout
+.Op Fl t Ar timeout
+.Op Fl u Ar default umask
+.Sh DESCRIPTION
+.Nm Ftpd
+is the
+Internet File Transfer Protocol
+server process. The server uses the
+.Tn TCP
+protocol
+and listens at the port specified in the
+.Dq ftp
+service specification; see
+.Xr services 5 .
+.Pp
+Available options:
+.Bl -tag -width Ds
+.It Fl a
+Select the level of authentication required. Kerberised login can not
+be turned off. The default is to only allow kerberised login. Other
+possibilities can be turned on by giving a string of comma separated
+flags as argument to
+.Fl a .
+Recognised flags are:
+.Bl -tag -width plain
+.It Ar plain
+Allow logging in with plaintext password. The password can be a(n) OTP
+or an ordinary password.
+.It Ar otp
+Same as
+.Ar plain ,
+but only OTP is allowed.
+.It Ar ftp
+Allow anonymous login.
+.El
+
+The following combination modes exists for backwards compatibility:
+.Bl -tag -width plain
+.It Ar none
+Same as
+.Ar plain,ftp .
+.It Ar safe
+Same as
+.Ar ftp .
+.It Ar user
+Ignored.
+.El
+.It Fl d
+Debugging information is written to the syslog using LOG_FTP.
+.It Fl g
+Anonymous users will get a umask of
+.Ar umask .
+.It Fl i
+Open a socket and wait for a connection. This is mainly used for
+debugging when ftpd isn't started by inetd.
+.It Fl l
+Each successful and failed
+.Xr ftp 1
+session is logged using syslog with a facility of LOG_FTP.
+If this option is specified twice, the retrieve (get), store (put), append,
+delete, make directory, remove directory and rename operations and
+their filename arguments are also logged.
+.It Fl p
+Use
+.Ar port
+(a service name or number) instead of the default
+.Ar ftp/tcp .
+.It Fl T
+A client may also request a different timeout period;
+the maximum period allowed may be set to
+.Ar timeout
+seconds with the
+.Fl T
+option.
+The default limit is 2 hours.
+.It Fl t
+The inactivity timeout period is set to
+.Ar timeout
+seconds (the default is 15 minutes).
+.It Fl u
+Set the initial umask to something else than the default 027.
+.It Fl v
+Verbose mode.
+.El
+.Pp
+The file
+.Pa /etc/nologin
+can be used to disable ftp access.
+If the file exists,
+.Nm
+displays it and exits.
+If the file
+.Pa /etc/ftpwelcome
+exists,
+.Nm
+prints it before issuing the
+.Dq ready
+message.
+If the file
+.Pa /etc/motd
+exists,
+.Nm
+prints it after a successful login.
+.Pp
+The ftp server currently supports the following ftp requests.
+The case of the requests is ignored.
+.Bl -column "Request" -offset indent
+.It Request Ta "Description"
+.It ABOR Ta "abort previous command"
+.It ACCT Ta "specify account (ignored)"
+.It ALLO Ta "allocate storage (vacuously)"
+.It APPE Ta "append to a file"
+.It CDUP Ta "change to parent of current working directory"
+.It CWD Ta "change working directory"
+.It DELE Ta "delete a file"
+.It HELP Ta "give help information"
+.It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA"
+.It MKD Ta "make a directory"
+.It MDTM Ta "show last modification time of file"
+.It MODE Ta "specify data transfer" Em mode
+.It NLST Ta "give name list of files in directory"
+.It NOOP Ta "do nothing"
+.It PASS Ta "specify password"
+.It PASV Ta "prepare for server-to-server transfer"
+.It PORT Ta "specify data connection port"
+.It PWD Ta "print the current working directory"
+.It QUIT Ta "terminate session"
+.It REST Ta "restart incomplete transfer"
+.It RETR Ta "retrieve a file"
+.It RMD Ta "remove a directory"
+.It RNFR Ta "specify rename-from file name"
+.It RNTO Ta "specify rename-to file name"
+.It SITE Ta "non-standard commands (see next section)"
+.It SIZE Ta "return size of file"
+.It STAT Ta "return status of server"
+.It STOR Ta "store a file"
+.It STOU Ta "store a file with a unique name"
+.It STRU Ta "specify data transfer" Em structure
+.It SYST Ta "show operating system type of server system"
+.It TYPE Ta "specify data transfer" Em type
+.It USER Ta "specify user name"
+.It XCUP Ta "change to parent of current working directory (deprecated)"
+.It XCWD Ta "change working directory (deprecated)"
+.It XMKD Ta "make a directory (deprecated)"
+.It XPWD Ta "print the current working directory (deprecated)"
+.It XRMD Ta "remove a directory (deprecated)"
+.El
+.Pp
+The following commands are specified by RFC2228.
+.Bl -column Request -offset indent
+.It AUTH Ta "authentication/security mechanism"
+.It ADAT Ta "authentication/security data"
+.It PROT Ta "data channel protection level"
+.It PBSZ Ta "protection buffer size"
+.It MIC Ta "integrity protected command"
+.It CONF Ta "confidentiality protected command"
+.It ENC Ta "privacy protected command"
+.It CCC Ta "clear command channel"
+.El
+.Pp
+The following non-standard or
+.Tn UNIX
+specific commands are supported
+by the
+SITE request.
+.Pp
+.Bl -column Request -offset indent
+.It UMASK Ta change umask, (e.g.
+.Ic "SITE UMASK 002" )
+.It IDLE Ta set idle-timer, (e.g.
+.Ic "SITE IDLE 60" )
+.It CHMOD Ta change mode of a file (e.g.
+.Ic "SITE CHMOD 755 filename" )
+.It FIND Ta quickly find a specific file with GNU
+.Xr locate 1 .
+.It HELP Ta give help information.
+.El
+.Pp
+The following Kerberos related site commands are understood.
+.Bl -column Request -offset indent
+.It KAUTH Ta obtain remote tickets.
+.It KLIST Ta show remote tickets
+.El
+.Pp
+The remaining ftp requests specified in Internet RFC 959
+are
+recognized, but not implemented.
+MDTM and SIZE are not specified in RFC 959, but will appear in the
+next updated FTP RFC.
+.Pp
+The ftp server will abort an active file transfer only when the
+ABOR
+command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC 959.
+If a
+STAT
+command is received during a data transfer, preceded by a Telnet IP
+and Synch, transfer status will be returned.
+.Pp
+.Nm Ftpd
+interprets file names according to the
+.Dq globbing
+conventions used by
+.Xr csh 1 .
+This allows users to utilize the metacharacters
+.Dq Li \&*?[]{}~ .
+.Pp
+.Nm Ftpd
+authenticates users according to these rules.
+.Pp
+.Bl -enum -offset indent
+.It
+If Kerberos authentication is used, the user must pass valid tickets
+and the principal must be allowed to login as the remote user.
+.It
+The login name must be in the password data base, and not have a null
+password (if kerberos is used the password field is not checked). In
+this case a password must be provided by the client before any file
+operations may be performed. If the user has an OTP key, the response
+from a successful USER command will include an OTP challenge. The
+client may choose to respond with a PASS command giving either a
+standard password or an OTP one-time password. The server will
+automatically determine which type of password it has been given and
+attempt to authenticate accordingly. See
+.Xr otp 1
+for more information on OTP authentication.
+.It
+The login name must not appear in the file
+.Pa /etc/ftpusers .
+.It
+The user must have a standard shell returned by
+.Xr getusershell 3 .
+.It
+If the user name appears in the file
+.Pa /etc/ftpchroot
+the session's root will be changed to the user's login directory by
+.Xr chroot 2
+as for an
+.Dq anonymous
+or
+.Dq ftp
+account (see next item). However, the user must still supply a password.
+This feature is intended as a compromise between a fully anonymous account
+and a fully privileged account. The account should also be set up as for an
+anonymous account.
+.It
+If the user name is
+.Dq anonymous
+or
+.Dq ftp ,
+an
+anonymous ftp account must be present in the password
+file (user
+.Dq ftp ) .
+In this case the user is allowed
+to log in by specifying any password (by convention an email address for
+the user should be used as the password).
+.El
+.Pp
+In the last case,
+.Nm ftpd
+takes special measures to restrict the client's access privileges.
+The server performs a
+.Xr chroot 2
+to the home directory of the
+.Dq ftp
+user.
+In order that system security is not breached, it is recommended
+that the
+.Dq ftp
+subtree be constructed with care, consider following these guidelines
+for anonymous ftp.
+
+In general all files should be owned by
+.Dq root ,
+and have non-write permissions (644 or 755 depending on the kind of
+file). No files should be owned or writable by
+.Dq ftp
+(possibly with exception for the
+.Pa ~ftp/incoming ,
+as specified below).
+.Bl -tag -width "~ftp/pub" -offset indent
+.It Pa ~ftp
+The
+.Dq ftp
+homedirectory should be owned by root.
+.It Pa ~ftp/bin
+The directory for external programs (such as
+.Xr ls 1 ) .
+These programs must either be statically linked, or you must setup an
+environment for dynamic linking when running chrooted.
+These programs will be used if present:
+.Bl -tag -width "locate" -offset indent
+.It ls
+Used when listing files.
+.It compress
+When retrieving a filename that ends in
+.Pa .Z ,
+and that file isn't present,
+.Nm
+will try to find the filename without
+.Pa .Z
+and compress it on the fly.
+.It gzip
+Same as compress, just with files ending in
+.Pa .gz .
+.It gtar
+Enables retrieval of whole directories as files ending in
+.Pa .tar .
+Can also be combined with compression. You must use GNU Tar (or some
+other that supports the
+.Fl z
+and
+.Fl Z
+flags).
+.It locate
+Will enable ``fast find'' with the
+.Ic SITE FIND
+command. You must also create a
+.Pa locatedb
+file in
+.Pa ~ftp/etc .
+.El
+.It Pa ~ftp/etc
+If you put copies of the
+.Xr passwd 5
+and
+.Xr group 5
+files here, ls will be able to produce owner names rather than
+numbers. Remember to remove any passwords from these files.
+
+The file
+.Pa motd ,
+if present, will be printed after a successful login.
+.It Pa ~ftp/dev
+Put a copy of
+.Xr /dev/null 7
+here.
+.It Pa ~ftp/pub
+Traditional place to put whatever you want to make public.
+.El
+
+If you want guests to be able to upload files, create a
+.Pa ~ftp/incoming
+directory owned by
+.Dq root ,
+and group
+.Dq ftp
+with mode 730 (make sure
+.Dq ftp
+is member of group
+.Dq ftp ) .
+The following restrictions apply to anonymous users:
+.Bl -bullet
+.It
+Directories created will have mode 700.
+.It
+Uploaded files will be created with an umask of 777, if not changed
+with the
+.Fl g
+option.
+.It
+These command are not accessible:
+.Ic DELE , RMD , RNTO , RNFR ,
+.Ic SITE UMASK ,
+and
+.Ic SITE CHMOD .
+.It
+Filenames must start with an alpha-numeric character, and consist of
+alpha-numeric characters or any of the following:
+.Li \&+
+(plus),
+.Li \&-
+(minus),
+.Li \&=
+(equal),
+.Li \&_
+(underscore),
+.Li \&.
+(period), and
+.Li \&,
+(comma).
+.El
+.Sh FILES
+.Bl -tag -width /etc/ftpwelcome -compact
+.It Pa /etc/ftpusers
+Access list for users.
+.It Pa /etc/ftpchroot
+List of normal users who should be chroot'd.
+.It Pa /etc/ftpwelcome
+Welcome notice.
+.It Pa /etc/motd
+Welcome notice after login.
+.It Pa /etc/nologin
+Displayed and access refused.
+.It Pa ~/.klogin
+Login access for Kerberos.
+.El
+.Sh SEE ALSO
+.Xr ftp 1 ,
+.Xr otp 1 ,
+.Xr getusershell 3 ,
+.Xr ftpusers 5 ,
+.Xr syslogd 8 ,
+.Sh STANDARDS
+.Bl -tag -compact -width "RFC 1938"
+.It Cm RFC 959
+FTP PROTOCOL SPECIFICATION
+.It Cm RFC 1938
+OTP Specification
+.It Cm RFC 2228
+FTP Security Extensions.
+.Sh BUGS
+The server must run as the super-user
+to create sockets with privileged port numbers. It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets. The
+possible security holes have been extensively
+scrutinized, but are possibly incomplete.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd.c b/crypto/heimdal/appl/ftp/ftpd/ftpd.c
new file mode 100644
index 0000000..8c5ddf3
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ftpd.c
@@ -0,0 +1,2249 @@
+/*
+ * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
+ * 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.
+ */
+
+#define FTP_NAMES
+#include "ftpd_locl.h"
+#ifdef KRB5
+#include <krb5.h>
+#endif
+#include "getarg.h"
+
+RCSID("$Id: ftpd.c,v 1.137 2000/01/05 13:46:04 joda Exp $");
+
+static char version[] = "Version 6.00";
+
+extern off_t restart_point;
+extern char cbuf[];
+
+struct sockaddr_storage ctrl_addr_ss;
+struct sockaddr *ctrl_addr = (struct sockaddr *)&ctrl_addr_ss;
+
+struct sockaddr_storage data_source_ss;
+struct sockaddr *data_source = (struct sockaddr *)&data_source_ss;
+
+struct sockaddr_storage data_dest_ss;
+struct sockaddr *data_dest = (struct sockaddr *)&data_dest_ss;
+
+struct sockaddr_storage his_addr_ss;
+struct sockaddr *his_addr = (struct sockaddr *)&his_addr_ss;
+
+struct sockaddr_storage pasv_addr_ss;
+struct sockaddr *pasv_addr = (struct sockaddr *)&pasv_addr_ss;
+
+int data;
+jmp_buf errcatch, urgcatch;
+int oobflag;
+int logged_in;
+struct passwd *pw;
+int debug = 0;
+int ftpd_timeout = 900; /* timeout after 15 minutes of inactivity */
+int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
+int logging;
+int guest;
+int dochroot;
+int type;
+int form;
+int stru; /* avoid C keyword */
+int mode;
+int usedefault = 1; /* for data transfers */
+int pdata = -1; /* for passive mode */
+int transflag;
+off_t file_size;
+off_t byte_count;
+#if !defined(CMASK) || CMASK == 0
+#undef CMASK
+#define CMASK 027
+#endif
+int defumask = CMASK; /* default umask value */
+int guest_umask = 0777; /* Paranoia for anonymous users */
+char tmpline[10240];
+char hostname[MaxHostNameLen];
+char remotehost[MaxHostNameLen];
+static char ttyline[20];
+
+#define AUTH_PLAIN (1 << 0) /* allow sending passwords */
+#define AUTH_OTP (1 << 1) /* passwords are one-time */
+#define AUTH_FTP (1 << 2) /* allow anonymous login */
+
+static int auth_level = 0; /* Only allow kerberos login by default */
+
+/*
+ * Timeout intervals for retrying connections
+ * to hosts that don't accept PORT cmds. This
+ * is a kludge, but given the problems with TCP...
+ */
+#define SWAITMAX 90 /* wait at most 90 seconds */
+#define SWAITINT 5 /* interval between retries */
+
+int swaitmax = SWAITMAX;
+int swaitint = SWAITINT;
+
+#ifdef HAVE_SETPROCTITLE
+char proctitle[BUFSIZ]; /* initial part of title */
+#endif /* HAVE_SETPROCTITLE */
+
+#define LOGCMD(cmd, file) \
+ if (logging > 1) \
+ syslog(LOG_INFO,"%s %s%s", cmd, \
+ *(file) == '/' ? "" : curdir(), file);
+#define LOGCMD2(cmd, file1, file2) \
+ if (logging > 1) \
+ syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
+ *(file1) == '/' ? "" : curdir(), file1, \
+ *(file2) == '/' ? "" : curdir(), file2);
+#define LOGBYTES(cmd, file, cnt) \
+ if (logging > 1) { \
+ if (cnt == (off_t)-1) \
+ syslog(LOG_INFO,"%s %s%s", cmd, \
+ *(file) == '/' ? "" : curdir(), file); \
+ else \
+ syslog(LOG_INFO, "%s %s%s = %ld bytes", \
+ cmd, (*(file) == '/') ? "" : curdir(), file, (long)cnt); \
+ }
+
+static void ack (char *);
+static void myoob (int);
+static int checkuser (char *, char *);
+static int checkaccess (char *);
+static FILE *dataconn (const char *, off_t, const char *);
+static void dolog (struct sockaddr *sa, int len);
+static void end_login (void);
+static FILE *getdatasock (const char *);
+static char *gunique (char *);
+static RETSIGTYPE lostconn (int);
+static int receive_data (FILE *, FILE *);
+static void send_data (FILE *, FILE *);
+static struct passwd * sgetpwnam (char *);
+
+static char *
+curdir(void)
+{
+ static char path[MaxPathLen+1]; /* path + '/' + '\0' */
+
+ if (getcwd(path, sizeof(path)-1) == NULL)
+ return ("");
+ if (path[1] != '\0') /* special case for root dir. */
+ strlcat(path, "/", sizeof(path));
+ /* For guest account, skip / since it's chrooted */
+ return (guest ? path+1 : path);
+}
+
+#ifndef LINE_MAX
+#define LINE_MAX 1024
+#endif
+
+static int
+parse_auth_level(char *str)
+{
+ char *p;
+ int ret = 0;
+ char *foo = NULL;
+
+ for(p = strtok_r(str, ",", &foo);
+ p;
+ p = strtok_r(NULL, ",", &foo)) {
+ if(strcmp(p, "user") == 0)
+ ;
+#ifdef OTP
+ else if(strcmp(p, "otp") == 0)
+ ret |= AUTH_PLAIN|AUTH_OTP;
+#endif
+ else if(strcmp(p, "ftp") == 0 ||
+ strcmp(p, "safe") == 0)
+ ret |= AUTH_FTP;
+ else if(strcmp(p, "plain") == 0)
+ ret |= AUTH_PLAIN;
+ else if(strcmp(p, "none") == 0)
+ ret |= AUTH_PLAIN|AUTH_FTP;
+ else
+ warnx("bad value for -a: `%s'", p);
+ }
+ return ret;
+}
+
+/*
+ * Print usage and die.
+ */
+
+static int debug_flag;
+static int interactive_flag;
+static char *guest_umask_string;
+static char *port_string;
+static char *umask_string;
+static char *auth_string;
+
+int use_builtin_ls = -1;
+
+static int help_flag;
+static int version_flag;
+
+struct getargs args[] = {
+ { NULL, 'a', arg_string, &auth_string, "required authentication" },
+ { NULL, 'i', arg_flag, &interactive_flag, "don't assume stdin is a socket" },
+ { NULL, 'p', arg_string, &port_string, "what port to listen to" },
+ { NULL, 'g', arg_string, &guest_umask_string, "umask for guest logins" },
+ { NULL, 'l', arg_counter, &logging, "log more stuff", "" },
+ { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout" },
+ { NULL, 'T', arg_integer, &maxtimeout, "max timeout" },
+ { NULL, 'u', arg_string, &umask_string, "umask for user logins" },
+ { NULL, 'd', arg_flag, &debug_flag, "enable debugging" },
+ { NULL, 'v', arg_flag, &debug_flag, "enable debugging" },
+ { "builtin-ls", 'B', arg_flag, &use_builtin_ls, "use built-in ls to list files" },
+ { "version", 0, arg_flag, &version_flag },
+ { "help", 'h', arg_flag, &help_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage (int code)
+{
+ arg_printusage(args, num_args, NULL, "");
+ exit (code);
+}
+
+/* output contents of a file */
+static int
+show_file(const char *file, int code)
+{
+ FILE *f;
+ char buf[128];
+
+ f = fopen(file, "r");
+ if(f == NULL)
+ return -1;
+ while(fgets(buf, sizeof(buf), f)){
+ buf[strcspn(buf, "\r\n")] = '\0';
+ lreply(code, "%s", buf);
+ }
+ fclose(f);
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int his_addr_len, ctrl_addr_len, on = 1, tos;
+ char *cp, line[LINE_MAX];
+ FILE *fd;
+ int port;
+ struct servent *sp;
+
+ int optind = 0;
+
+ set_progname (argv[0]);
+
+#ifdef KRB4
+ /* detach from any tickets and tokens */
+ {
+ char tkfile[1024];
+ snprintf(tkfile, sizeof(tkfile),
+ "/tmp/ftp_%u", (unsigned)getpid());
+ krb_set_tkt_string(tkfile);
+ if(k_hasafs())
+ k_setpag();
+ }
+#endif
+ if(getarg(args, num_args, argc, argv, &optind))
+ usage(1);
+
+ if(help_flag)
+ usage(0);
+
+ if(version_flag) {
+ print_version(NULL);
+ exit(0);
+ }
+
+ if(auth_string)
+ auth_level = parse_auth_level(auth_string);
+ {
+ char *p;
+ long val = 0;
+
+ if(guest_umask_string) {
+ val = strtol(guest_umask_string, &p, 8);
+ if (*p != '\0' || val < 0)
+ warnx("bad value for -g");
+ else
+ guest_umask = val;
+ }
+ if(umask_string) {
+ val = strtol(umask_string, &p, 8);
+ if (*p != '\0' || val < 0)
+ warnx("bad value for -u");
+ else
+ defumask = val;
+ }
+ }
+ if(port_string) {
+ sp = getservbyname(port_string, "tcp");
+ if(sp)
+ port = sp->s_port;
+ else
+ if(isdigit(port_string[0]))
+ port = htons(atoi(port_string));
+ else
+ warnx("bad value for -p");
+ } else {
+ sp = getservbyname("ftp", "tcp");
+ if(sp)
+ port = sp->s_port;
+ else
+ port = htons(21);
+ }
+
+ if (maxtimeout < ftpd_timeout)
+ maxtimeout = ftpd_timeout;
+
+#if 0
+ if (ftpd_timeout > maxtimeout)
+ ftpd_timeout = maxtimeout;
+#endif
+
+ if(interactive_flag)
+ mini_inetd (port);
+
+ /*
+ * LOG_NDELAY sets up the logging connection immediately,
+ * necessary for anonymous ftp's that chroot and can't do it later.
+ */
+ openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
+ his_addr_len = sizeof(his_addr_ss);
+ if (getpeername(STDIN_FILENO, his_addr, &his_addr_len) < 0) {
+ syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
+ exit(1);
+ }
+ ctrl_addr_len = sizeof(ctrl_addr_ss);
+ if (getsockname(STDIN_FILENO, ctrl_addr, &ctrl_addr_len) < 0) {
+ syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
+ exit(1);
+ }
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ tos = IPTOS_LOWDELAY;
+ if (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS,
+ (void *)&tos, sizeof(int)) < 0)
+ syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
+#endif
+ data_source->sa_family = ctrl_addr->sa_family;
+ socket_set_port (data_source,
+ htons(ntohs(socket_get_port(ctrl_addr)) - 1));
+
+ /* set this here so it can be put in wtmp */
+ snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid());
+
+
+ /* freopen(_PATH_DEVNULL, "w", stderr); */
+ signal(SIGPIPE, lostconn);
+ signal(SIGCHLD, SIG_IGN);
+#ifdef SIGURG
+ if (signal(SIGURG, myoob) == SIG_ERR)
+ syslog(LOG_ERR, "signal: %m");
+#endif
+
+ /* Try to handle urgent data inline */
+#if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
+ if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on,
+ sizeof(on)) < 0)
+ syslog(LOG_ERR, "setsockopt: %m");
+#endif
+
+#ifdef F_SETOWN
+ if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
+ syslog(LOG_ERR, "fcntl F_SETOWN: %m");
+#endif
+ dolog(his_addr, his_addr_len);
+ /*
+ * Set up default state
+ */
+ data = -1;
+ type = TYPE_A;
+ form = FORM_N;
+ stru = STRU_F;
+ mode = MODE_S;
+ tmpline[0] = '\0';
+
+ /* If logins are disabled, print out the message. */
+ if(show_file(_PATH_NOLOGIN, 530) == 0) {
+ reply(530, "System not available.");
+ exit(0);
+ }
+ show_file(_PATH_FTPWELCOME, 220);
+ /* reply(220,) must follow */
+ gethostname(hostname, sizeof(hostname));
+
+ reply(220, "%s FTP server (%s"
+#ifdef KRB5
+ "+%s"
+#endif
+#ifdef KRB4
+ "+%s"
+#endif
+ ") ready.", hostname, version
+#ifdef KRB5
+ ,heimdal_version
+#endif
+#ifdef KRB4
+ ,krb4_version
+#endif
+ );
+
+ setjmp(errcatch);
+ for (;;)
+ yyparse();
+ /* NOTREACHED */
+}
+
+static RETSIGTYPE
+lostconn(int signo)
+{
+
+ if (debug)
+ syslog(LOG_DEBUG, "lost connection");
+ dologout(-1);
+}
+
+/*
+ * Helper function for sgetpwnam().
+ */
+static char *
+sgetsave(char *s)
+{
+ char *new = strdup(s);
+
+ if (new == NULL) {
+ perror_reply(421, "Local resource failure: malloc");
+ dologout(1);
+ /* NOTREACHED */
+ }
+ return new;
+}
+
+/*
+ * Save the result of a getpwnam. Used for USER command, since
+ * the data returned must not be clobbered by any other command
+ * (e.g., globbing).
+ */
+static struct passwd *
+sgetpwnam(char *name)
+{
+ static struct passwd save;
+ struct passwd *p;
+
+ if ((p = k_getpwnam(name)) == NULL)
+ return (p);
+ if (save.pw_name) {
+ free(save.pw_name);
+ free(save.pw_passwd);
+ free(save.pw_gecos);
+ free(save.pw_dir);
+ free(save.pw_shell);
+ }
+ save = *p;
+ save.pw_name = sgetsave(p->pw_name);
+ save.pw_passwd = sgetsave(p->pw_passwd);
+ save.pw_gecos = sgetsave(p->pw_gecos);
+ save.pw_dir = sgetsave(p->pw_dir);
+ save.pw_shell = sgetsave(p->pw_shell);
+ return (&save);
+}
+
+static int login_attempts; /* number of failed login attempts */
+static int askpasswd; /* had user command, ask for passwd */
+static char curname[10]; /* current USER name */
+#ifdef OTP
+OtpContext otp_ctx;
+#endif
+
+/*
+ * USER command.
+ * Sets global passwd pointer pw if named account exists and is acceptable;
+ * sets askpasswd if a PASS command is expected. If logged in previously,
+ * need to reset state. If name is "ftp" or "anonymous", the name is not in
+ * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
+ * If account doesn't exist, ask for passwd anyway. Otherwise, check user
+ * requesting login privileges. Disallow anyone who does not have a standard
+ * shell as returned by getusershell(). Disallow anyone mentioned in the file
+ * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ */
+void
+user(char *name)
+{
+ char *cp, *shell;
+
+ if(auth_level == 0 && !sec_complete){
+ reply(530, "No login allowed without authorization.");
+ return;
+ }
+
+ if (logged_in) {
+ if (guest) {
+ reply(530, "Can't change user from guest login.");
+ return;
+ } else if (dochroot) {
+ reply(530, "Can't change user from chroot user.");
+ return;
+ }
+ end_login();
+ }
+
+ guest = 0;
+ if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
+ if ((auth_level & AUTH_FTP) == 0 ||
+ checkaccess("ftp") ||
+ checkaccess("anonymous"))
+ reply(530, "User %s access denied.", name);
+ else if ((pw = sgetpwnam("ftp")) != NULL) {
+ guest = 1;
+ defumask = guest_umask; /* paranoia for incoming */
+ askpasswd = 1;
+ reply(331, "Guest login ok, type your name as password.");
+ } else
+ reply(530, "User %s unknown.", name);
+ if (!askpasswd && logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_NOTICE,
+ "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)",
+ remotehost, data_addr);
+ }
+ return;
+ }
+ if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){
+ reply(530, "Only authorized and anonymous login allowed.");
+ return;
+ }
+ if ((pw = sgetpwnam(name))) {
+ if ((shell = pw->pw_shell) == NULL || *shell == 0)
+ shell = _PATH_BSHELL;
+ while ((cp = getusershell()) != NULL)
+ if (strcmp(cp, shell) == 0)
+ break;
+ endusershell();
+
+ if (cp == NULL || checkaccess(name)) {
+ reply(530, "User %s access denied.", name);
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr,
+ sizeof(data_addr)) == NULL)
+ strlcpy (data_addr,
+ "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_NOTICE,
+ "FTP LOGIN REFUSED FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ name);
+ }
+ pw = (struct passwd *) NULL;
+ return;
+ }
+ }
+ if (logging)
+ strlcpy(curname, name, sizeof(curname));
+ if(sec_complete) {
+ if(sec_userok(name) == 0)
+ do_login(232, name);
+ else
+ reply(530, "User %s access denied.", name);
+ } else {
+ char ss[256];
+
+#ifdef OTP
+ if (otp_challenge(&otp_ctx, name, ss, sizeof(ss)) == 0) {
+ reply(331, "Password %s for %s required.",
+ ss, name);
+ askpasswd = 1;
+ } else
+#endif
+ if ((auth_level & AUTH_OTP) == 0) {
+ reply(331, "Password required for %s.", name);
+ askpasswd = 1;
+ } else {
+ char *s;
+
+#ifdef OTP
+ if ((s = otp_error (&otp_ctx)) != NULL)
+ lreply(530, "OTP: %s", s);
+#endif
+ reply(530,
+ "Only authorized, anonymous"
+#ifdef OTP
+ " and OTP "
+#endif
+ "login allowed.");
+ }
+
+ }
+ /*
+ * Delay before reading passwd after first failed
+ * attempt to slow down passwd-guessing programs.
+ */
+ if (login_attempts)
+ sleep(login_attempts);
+}
+
+/*
+ * Check if a user is in the file "fname"
+ */
+static int
+checkuser(char *fname, char *name)
+{
+ FILE *fd;
+ int found = 0;
+ char *p, line[BUFSIZ];
+
+ if ((fd = fopen(fname, "r")) != NULL) {
+ while (fgets(line, sizeof(line), fd) != NULL)
+ if ((p = strchr(line, '\n')) != NULL) {
+ *p = '\0';
+ if (line[0] == '#')
+ continue;
+ if (strcmp(line, name) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ fclose(fd);
+ }
+ return (found);
+}
+
+
+/*
+ * Determine whether a user has access, based on information in
+ * _PATH_FTPUSERS. The users are listed one per line, with `allow'
+ * or `deny' after the username. If anything other than `allow', or
+ * just nothing, is given after the username, `deny' is assumed.
+ *
+ * If the user is not found in the file, but the pseudo-user `*' is,
+ * the permission is taken from that line.
+ *
+ * This preserves the old semantics where if a user was listed in the
+ * file he was denied, otherwise he was allowed.
+ *
+ * Return 1 if the user is denied, or 0 if he is allowed. */
+
+static int
+match(const char *pattern, const char *string)
+{
+ return fnmatch(pattern, string, FNM_NOESCAPE);
+}
+
+static int
+checkaccess(char *name)
+{
+#define ALLOWED 0
+#define NOT_ALLOWED 1
+ FILE *fd;
+ int allowed = ALLOWED;
+ char *user, *perm, line[BUFSIZ];
+ char *foo;
+
+ fd = fopen(_PATH_FTPUSERS, "r");
+
+ if(fd == NULL)
+ return allowed;
+
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ foo = NULL;
+ user = strtok_r(line, " \t\n", &foo);
+ if (user == NULL || user[0] == '#')
+ continue;
+ perm = strtok_r(NULL, " \t\n", &foo);
+ if (match(user, name) == 0){
+ if(perm && strcmp(perm, "allow") == 0)
+ allowed = ALLOWED;
+ else
+ allowed = NOT_ALLOWED;
+ break;
+ }
+ }
+ fclose(fd);
+ return allowed;
+}
+#undef ALLOWED
+#undef NOT_ALLOWED
+
+
+int do_login(int code, char *passwd)
+{
+ FILE *fd;
+ login_attempts = 0; /* this time successful */
+ if (setegid((gid_t)pw->pw_gid) < 0) {
+ reply(550, "Can't set gid.");
+ return -1;
+ }
+ initgroups(pw->pw_name, pw->pw_gid);
+
+ /* open wtmp before chroot */
+ ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
+ logged_in = 1;
+
+ dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);
+ if (guest) {
+ /*
+ * We MUST do a chdir() after the chroot. Otherwise
+ * the old current directory will be accessible as "."
+ * outside the new root!
+ */
+ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ reply(550, "Can't set guest privileges.");
+ return -1;
+ }
+ } else if (dochroot) {
+ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ reply(550, "Can't change root.");
+ return -1;
+ }
+ } else if (chdir(pw->pw_dir) < 0) {
+ if (chdir("/") < 0) {
+ reply(530, "User %s: can't change directory to %s.",
+ pw->pw_name, pw->pw_dir);
+ return -1;
+ } else
+ lreply(code, "No directory! Logging in with home=/");
+ }
+ if (seteuid((uid_t)pw->pw_uid) < 0) {
+ reply(550, "Can't set uid.");
+ return -1;
+ }
+
+ if(use_builtin_ls == -1) {
+ struct stat st;
+ /* if /bin/ls exist and is a regular file, use it, otherwise
+ use built-in ls */
+ if(stat("/bin/ls", &st) == 0 &&
+ S_ISREG(st.st_mode))
+ use_builtin_ls = 0;
+ else
+ use_builtin_ls = 1;
+ }
+
+ /*
+ * Display a login message, if it exists.
+ * N.B. reply(code,) must follow the message.
+ */
+ show_file(_PATH_FTPLOGINMESG, code);
+ if(show_file(_PATH_ISSUE_NET, code) != 0)
+ show_file(_PATH_ISSUE, code);
+ if (guest) {
+ reply(code, "Guest login ok, access restrictions apply.");
+#ifdef HAVE_SETPROCTITLE
+ snprintf (proctitle, sizeof(proctitle),
+ "%s: anonymous/%s",
+ remotehost,
+ passwd);
+ setproctitle(proctitle);
+#endif /* HAVE_SETPROCTITLE */
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ passwd);
+ }
+ } else {
+ reply(code, "User %s logged in.", pw->pw_name);
+#ifdef HAVE_SETPROCTITLE
+ snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name);
+ setproctitle(proctitle);
+#endif /* HAVE_SETPROCTITLE */
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s",
+ remotehost,
+ data_addr,
+ pw->pw_name);
+ }
+ }
+ umask(defumask);
+ return 0;
+}
+
+/*
+ * Terminate login as previous user, if any, resetting state;
+ * used when USER command is given or login fails.
+ */
+static void
+end_login(void)
+{
+
+ seteuid((uid_t)0);
+ if (logged_in)
+ ftpd_logwtmp(ttyline, "", "");
+ pw = NULL;
+ logged_in = 0;
+ guest = 0;
+ dochroot = 0;
+}
+
+void
+pass(char *passwd)
+{
+ int rval;
+
+ /* some clients insists on sending a password */
+ if (logged_in && askpasswd == 0){
+ reply(230, "Dumpucko!");
+ return;
+ }
+
+ if (logged_in || askpasswd == 0) {
+ reply(503, "Login with USER first.");
+ return;
+ }
+ askpasswd = 0;
+ rval = 1;
+ if (!guest) { /* "ftp" is only account allowed no password */
+ if (pw == NULL)
+ rval = 1; /* failure below */
+#ifdef OTP
+ else if (otp_verify_user (&otp_ctx, passwd) == 0) {
+ rval = 0;
+ }
+#endif
+ else if((auth_level & AUTH_OTP) == 0) {
+#ifdef KRB4
+ char realm[REALM_SZ];
+ if((rval = krb_get_lrealm(realm, 1)) == KSUCCESS)
+ rval = krb_verify_user(pw->pw_name,
+ "", realm,
+ passwd,
+ KRB_VERIFY_SECURE, NULL);
+ if (rval == KSUCCESS ) {
+ chown (tkt_string(), pw->pw_uid, pw->pw_gid);
+ if(k_hasafs())
+ krb_afslog(0, 0);
+ } else
+#endif
+ rval = unix_verify_user(pw->pw_name, passwd);
+ } else {
+ char *s;
+
+#ifdef OTP
+ if ((s = otp_error(&otp_ctx)) != NULL)
+ lreply(530, "OTP: %s", s);
+#endif
+ }
+ memset (passwd, 0, strlen(passwd));
+
+ /*
+ * If rval == 1, the user failed the authentication
+ * check above. If rval == 0, either Kerberos or
+ * local authentication succeeded.
+ */
+ if (rval) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ reply(530, "Login incorrect.");
+ if (logging)
+ syslog(LOG_NOTICE,
+ "FTP LOGIN FAILED FROM %s(%s), %s",
+ remotehost,
+ data_addr,
+ curname);
+ pw = NULL;
+ if (login_attempts++ >= 5) {
+ syslog(LOG_NOTICE,
+ "repeated login failures from %s(%s)",
+ remotehost,
+ data_addr);
+ exit(0);
+ }
+ return;
+ }
+ }
+ if(!do_login(230, passwd))
+ return;
+
+ /* Forget all about it... */
+ end_login();
+}
+
+void
+retrieve(const char *cmd, char *name)
+{
+ FILE *fin = NULL, *dout;
+ struct stat st;
+ int (*closefunc) (FILE *);
+ char line[BUFSIZ];
+
+
+ if (cmd == 0) {
+ fin = fopen(name, "r");
+ closefunc = fclose;
+ st.st_size = 0;
+ if(fin == NULL){
+ int save_errno = errno;
+ struct cmds {
+ const char *ext;
+ const char *cmd;
+ const char *rev_cmd;
+ } cmds[] = {
+ {".tar", "/bin/gtar cPf - %s", NULL},
+ {".tar.gz", "/bin/gtar zcPf - %s", NULL},
+ {".tar.Z", "/bin/gtar ZcPf - %s", NULL},
+ {".gz", "/bin/gzip -c -- %s", "/bin/gzip -c -d -- %s"},
+ {".Z", "/bin/compress -c -- %s", "/bin/uncompress -c -- %s"},
+ {NULL, NULL}
+ };
+ struct cmds *p;
+ for(p = cmds; p->ext; p++){
+ char *tail = name + strlen(name) - strlen(p->ext);
+ char c = *tail;
+
+ if(strcmp(tail, p->ext) == 0 &&
+ (*tail = 0) == 0 &&
+ access(name, R_OK) == 0){
+ snprintf (line, sizeof(line), p->cmd, name);
+ *tail = c;
+ break;
+ }
+ *tail = c;
+ if (p->rev_cmd != NULL) {
+ char *ext;
+
+ asprintf(&ext, "%s%s", name, p->ext);
+ if (ext != NULL) {
+ if (access(ext, R_OK) == 0) {
+ snprintf (line, sizeof(line),
+ p->rev_cmd, ext);
+ free(ext);
+ break;
+ }
+ free(ext);
+ }
+ }
+
+ }
+ if(p->ext){
+ fin = ftpd_popen(line, "r", 0, 0);
+ closefunc = ftpd_pclose;
+ st.st_size = -1;
+ cmd = line;
+ } else
+ errno = save_errno;
+ }
+ } else {
+ snprintf(line, sizeof(line), cmd, name);
+ name = line;
+ fin = ftpd_popen(line, "r", 1, 0);
+ closefunc = ftpd_pclose;
+ st.st_size = -1;
+ }
+ if (fin == NULL) {
+ if (errno != 0) {
+ perror_reply(550, name);
+ if (cmd == 0) {
+ LOGCMD("get", name);
+ }
+ }
+ return;
+ }
+ byte_count = -1;
+ if (cmd == 0){
+ if(fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) {
+ reply(550, "%s: not a plain file.", name);
+ goto done;
+ }
+ }
+ if (restart_point) {
+ if (type == TYPE_A) {
+ off_t i, n;
+ int c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c=getc(fin)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ } else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ dout = dataconn(name, st.st_size, "w");
+ if (dout == NULL)
+ goto done;
+ set_buffer_size(fileno(dout), 0);
+ send_data(fin, dout);
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+done:
+ if (cmd == 0)
+ LOGBYTES("get", name, byte_count);
+ (*closefunc)(fin);
+}
+
+/* filename sanity check */
+
+int
+filename_check(char *filename)
+{
+ static const char good_chars[] = "+-=_,.";
+ char *p;
+
+ p = strrchr(filename, '/');
+ if(p)
+ filename = p + 1;
+
+ p = filename;
+
+ if(isalnum(*p)){
+ p++;
+ while(*p && (isalnum(*p) || strchr(good_chars, *p)))
+ p++;
+ if(*p == '\0')
+ return 0;
+ }
+ lreply(553, "\"%s\" is an illegal filename.", filename);
+ lreply(553, "The filename must start with an alphanumeric "
+ "character and must only");
+ reply(553, "consist of alphanumeric characters or any of the following: %s",
+ good_chars);
+ return 1;
+}
+
+void
+do_store(char *name, char *mode, int unique)
+{
+ FILE *fout, *din;
+ struct stat st;
+ int (*closefunc) (FILE *);
+
+ if(guest && filename_check(name))
+ return;
+ if (unique && stat(name, &st) == 0 &&
+ (name = gunique(name)) == NULL) {
+ LOGCMD(*mode == 'w' ? "put" : "append", name);
+ return;
+ }
+
+ if (restart_point)
+ mode = "r+";
+ fout = fopen(name, mode);
+ closefunc = fclose;
+ if (fout == NULL) {
+ perror_reply(553, name);
+ LOGCMD(*mode == 'w' ? "put" : "append", name);
+ return;
+ }
+ byte_count = -1;
+ if (restart_point) {
+ if (type == TYPE_A) {
+ off_t i, n;
+ int c;
+
+ n = restart_point;
+ i = 0;
+ while (i++ < n) {
+ if ((c=getc(fout)) == EOF) {
+ perror_reply(550, name);
+ goto done;
+ }
+ if (c == '\n')
+ i++;
+ }
+ /*
+ * We must do this seek to "current" position
+ * because we are changing from reading to
+ * writing.
+ */
+ if (fseek(fout, 0L, SEEK_CUR) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ } else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
+ perror_reply(550, name);
+ goto done;
+ }
+ }
+ din = dataconn(name, (off_t)-1, "r");
+ if (din == NULL)
+ goto done;
+ set_buffer_size(fileno(din), 1);
+ if (receive_data(din, fout) == 0) {
+ if (unique)
+ reply(226, "Transfer complete (unique file name:%s).",
+ name);
+ else
+ reply(226, "Transfer complete.");
+ }
+ fclose(din);
+ data = -1;
+ pdata = -1;
+done:
+ LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
+ (*closefunc)(fout);
+}
+
+static FILE *
+getdatasock(const char *mode)
+{
+ int s, t, tries;
+
+ if (data >= 0)
+ return (fdopen(data, mode));
+ seteuid(0);
+ s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (s < 0)
+ goto bad;
+ socket_set_reuseaddr (s, 1);
+ /* anchor socket to avoid multi-homing problems */
+ socket_set_address_and_port (data_source,
+ socket_get_address (ctrl_addr),
+ socket_get_port (data_source));
+
+ for (tries = 1; ; tries++) {
+ if (bind(s, data_source,
+ socket_sockaddr_size (data_source)) >= 0)
+ break;
+ if (errno != EADDRINUSE || tries > 10)
+ goto bad;
+ sleep(tries);
+ }
+ seteuid(pw->pw_uid);
+#ifdef IPTOS_THROUGHPUT
+ socket_set_tos (s, IPTOS_THROUGHPUT);
+#endif
+ return (fdopen(s, mode));
+bad:
+ /* Return the real value of errno (close may change it) */
+ t = errno;
+ seteuid((uid_t)pw->pw_uid);
+ close(s);
+ errno = t;
+ return (NULL);
+}
+
+static FILE *
+dataconn(const char *name, off_t size, const char *mode)
+{
+ char sizebuf[32];
+ FILE *file;
+ int retry = 0;
+
+ file_size = size;
+ byte_count = 0;
+ if (size >= 0)
+ snprintf(sizebuf, sizeof(sizebuf), " (%ld bytes)", (long)size);
+ else
+ *sizebuf = '\0';
+ if (pdata >= 0) {
+ struct sockaddr_storage from_ss;
+ struct sockaddr *from = (struct sockaddr *)&from_ss;
+ int s;
+ int fromlen = sizeof(from_ss);
+
+ s = accept(pdata, from, &fromlen);
+ if (s < 0) {
+ reply(425, "Can't open data connection.");
+ close(pdata);
+ pdata = -1;
+ return (NULL);
+ }
+ close(pdata);
+ pdata = s;
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+ {
+ int tos = IPTOS_THROUGHPUT;
+
+ setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&tos,
+ sizeof(tos));
+ }
+#endif
+ reply(150, "Opening %s mode data connection for '%s'%s.",
+ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+ return (fdopen(pdata, mode));
+ }
+ if (data >= 0) {
+ reply(125, "Using existing data connection for '%s'%s.",
+ name, sizebuf);
+ usedefault = 1;
+ return (fdopen(data, mode));
+ }
+ if (usedefault)
+ data_dest = his_addr;
+ usedefault = 1;
+ file = getdatasock(mode);
+ if (file == NULL) {
+ char data_addr[256];
+
+ if (inet_ntop (data_source->sa_family,
+ socket_get_address(data_source),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+ reply(425, "Can't create data socket (%s,%d): %s.",
+ data_addr,
+ socket_get_port (data_source),
+ strerror(errno));
+ return (NULL);
+ }
+ data = fileno(file);
+ while (connect(data, data_dest,
+ socket_sockaddr_size(data_dest)) < 0) {
+ if (errno == EADDRINUSE && retry < swaitmax) {
+ sleep(swaitint);
+ retry += swaitint;
+ continue;
+ }
+ perror_reply(425, "Can't build data connection");
+ fclose(file);
+ data = -1;
+ return (NULL);
+ }
+ reply(150, "Opening %s mode data connection for '%s'%s.",
+ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+ return (file);
+}
+
+/*
+ * Tranfer the contents of "instr" to "outstr" peer using the appropriate
+ * encapsulation of the data subject * to Mode, Structure, and Type.
+ *
+ * NB: Form isn't handled.
+ */
+static void
+send_data(FILE *instr, FILE *outstr)
+{
+ int c, cnt, filefd, netfd;
+ static char *buf;
+ static size_t bufsize;
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return;
+ }
+ switch (type) {
+
+ case TYPE_A:
+ while ((c = getc(instr)) != EOF) {
+ byte_count++;
+ if(c == '\n')
+ sec_putc('\r', outstr);
+ sec_putc(c, outstr);
+ }
+ sec_fflush(outstr);
+ transflag = 0;
+ if (ferror(instr))
+ goto file_err;
+ if (ferror(outstr))
+ goto data_err;
+ reply(226, "Transfer complete.");
+ return;
+
+ case TYPE_I:
+ case TYPE_L:
+#if defined(HAVE_MMAP) && !defined(NO_MMAP)
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+ {
+ struct stat st;
+ char *chunk;
+ int in = fileno(instr);
+ if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)
+ && st.st_size > 0) {
+ /*
+ * mmap zero bytes has potential of loosing, don't do it.
+ */
+ chunk = mmap(0, st.st_size, PROT_READ,
+ MAP_SHARED, in, 0);
+ if((void *)chunk != (void *)MAP_FAILED) {
+ cnt = st.st_size - restart_point;
+ sec_write(fileno(outstr), chunk + restart_point, cnt);
+ if (munmap(chunk, st.st_size) < 0)
+ warn ("munmap");
+ sec_fflush(outstr);
+ byte_count = cnt;
+ transflag = 0;
+ }
+ }
+ }
+#endif
+ if(transflag) {
+ struct stat st;
+
+ netfd = fileno(outstr);
+ filefd = fileno(instr);
+ buf = alloc_buffer (buf, &bufsize,
+ fstat(filefd, &st) >= 0 ? &st : NULL);
+ if (buf == NULL) {
+ transflag = 0;
+ perror_reply(451, "Local resource failure: malloc");
+ return;
+ }
+ while ((cnt = read(filefd, buf, bufsize)) > 0 &&
+ sec_write(netfd, buf, cnt) == cnt)
+ byte_count += cnt;
+ sec_fflush(outstr); /* to end an encrypted stream */
+ transflag = 0;
+ if (cnt != 0) {
+ if (cnt < 0)
+ goto file_err;
+ goto data_err;
+ }
+ }
+ reply(226, "Transfer complete.");
+ return;
+ default:
+ transflag = 0;
+ reply(550, "Unimplemented TYPE %d in send_data", type);
+ return;
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data connection");
+ return;
+
+file_err:
+ transflag = 0;
+ perror_reply(551, "Error on input file");
+}
+
+/*
+ * Transfer data from peer to "outstr" using the appropriate encapulation of
+ * the data subject to Mode, Structure, and Type.
+ *
+ * N.B.: Form isn't handled.
+ */
+static int
+receive_data(FILE *instr, FILE *outstr)
+{
+ int cnt, bare_lfs = 0;
+ static char *buf;
+ static size_t bufsize;
+ struct stat st;
+
+ transflag++;
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ return (-1);
+ }
+
+ buf = alloc_buffer (buf, &bufsize,
+ fstat(fileno(outstr), &st) >= 0 ? &st : NULL);
+ if (buf == NULL) {
+ transflag = 0;
+ perror_reply(451, "Local resource failure: malloc");
+ return -1;
+ }
+
+ switch (type) {
+
+ case TYPE_I:
+ case TYPE_L:
+ while ((cnt = sec_read(fileno(instr), buf, bufsize)) > 0) {
+ if (write(fileno(outstr), buf, cnt) != cnt)
+ goto file_err;
+ byte_count += cnt;
+ }
+ if (cnt < 0)
+ goto data_err;
+ transflag = 0;
+ return (0);
+
+ case TYPE_E:
+ reply(553, "TYPE E not implemented.");
+ transflag = 0;
+ return (-1);
+
+ case TYPE_A:
+ {
+ char *p, *q;
+ int cr_flag = 0;
+ while ((cnt = sec_read(fileno(instr),
+ buf + cr_flag,
+ bufsize - cr_flag)) > 0){
+ byte_count += cnt;
+ cnt += cr_flag;
+ cr_flag = 0;
+ for(p = buf, q = buf; p < buf + cnt;) {
+ if(*p == '\n')
+ bare_lfs++;
+ if(*p == '\r') {
+ if(p == buf + cnt - 1){
+ cr_flag = 1;
+ p++;
+ continue;
+ }else if(p[1] == '\n'){
+ *q++ = '\n';
+ p += 2;
+ continue;
+ }
+ }
+ *q++ = *p++;
+ }
+ fwrite(buf, q - buf, 1, outstr);
+ if(cr_flag)
+ buf[0] = '\r';
+ }
+ if(cr_flag)
+ putc('\r', outstr);
+ fflush(outstr);
+ if (ferror(instr))
+ goto data_err;
+ if (ferror(outstr))
+ goto file_err;
+ transflag = 0;
+ if (bare_lfs) {
+ lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
+ " File may not have transferred correctly.\r\n",
+ bare_lfs);
+ }
+ return (0);
+ }
+ default:
+ reply(550, "Unimplemented TYPE %d in receive_data", type);
+ transflag = 0;
+ return (-1);
+ }
+
+data_err:
+ transflag = 0;
+ perror_reply(426, "Data Connection");
+ return (-1);
+
+file_err:
+ transflag = 0;
+ perror_reply(452, "Error writing file");
+ return (-1);
+}
+
+void
+statfilecmd(char *filename)
+{
+ FILE *fin;
+ int c;
+ char line[LINE_MAX];
+
+ snprintf(line, sizeof(line), "/bin/ls -la -- %s", filename);
+ fin = ftpd_popen(line, "r", 1, 0);
+ lreply(211, "status of %s:", filename);
+ while ((c = getc(fin)) != EOF) {
+ if (c == '\n') {
+ if (ferror(stdout)){
+ perror_reply(421, "control connection");
+ ftpd_pclose(fin);
+ dologout(1);
+ /* NOTREACHED */
+ }
+ if (ferror(fin)) {
+ perror_reply(551, filename);
+ ftpd_pclose(fin);
+ return;
+ }
+ putc('\r', stdout);
+ }
+ putc(c, stdout);
+ }
+ ftpd_pclose(fin);
+ reply(211, "End of Status");
+}
+
+void
+statcmd(void)
+{
+#if 0
+ struct sockaddr_in *sin;
+ u_char *a, *p;
+
+ lreply(211, "%s FTP server (%s) status:", hostname, version);
+ printf(" %s\r\n", version);
+ printf(" Connected to %s", remotehost);
+ if (!isdigit(remotehost[0]))
+ printf(" (%s)", inet_ntoa(his_addr.sin_addr));
+ printf("\r\n");
+ if (logged_in) {
+ if (guest)
+ printf(" Logged in anonymously\r\n");
+ else
+ printf(" Logged in as %s\r\n", pw->pw_name);
+ } else if (askpasswd)
+ printf(" Waiting for password\r\n");
+ else
+ printf(" Waiting for user name\r\n");
+ printf(" TYPE: %s", typenames[type]);
+ if (type == TYPE_A || type == TYPE_E)
+ printf(", FORM: %s", formnames[form]);
+ if (type == TYPE_L)
+#if NBBY == 8
+ printf(" %d", NBBY);
+#else
+ printf(" %d", bytesize); /* need definition! */
+#endif
+ printf("; STRUcture: %s; transfer MODE: %s\r\n",
+ strunames[stru], modenames[mode]);
+ if (data != -1)
+ printf(" Data connection open\r\n");
+ else if (pdata != -1) {
+ printf(" in Passive mode");
+ sin = &pasv_addr;
+ goto printaddr;
+ } else if (usedefault == 0) {
+ printf(" PORT");
+ sin = &data_dest;
+printaddr:
+ a = (u_char *) &sin->sin_addr;
+ p = (u_char *) &sin->sin_port;
+#define UC(b) (((int) b) & 0xff)
+ printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+#undef UC
+ } else
+ printf(" No data connection\r\n");
+#endif
+ reply(211, "End of status");
+}
+
+void
+fatal(char *s)
+{
+
+ reply(451, "Error in server: %s\n", s);
+ reply(221, "Closing connection due to server error.");
+ dologout(0);
+ /* NOTREACHED */
+}
+
+static void
+int_reply(int, char *, const char *, va_list)
+#ifdef __GNUC__
+__attribute__ ((format (printf, 3, 0)))
+#endif
+;
+
+static void
+int_reply(int n, char *c, const char *fmt, va_list ap)
+{
+ char buf[10240];
+ char *p;
+ p=buf;
+ if(n){
+ snprintf(p, sizeof(buf), "%d%s", n, c);
+ p+=strlen(p);
+ }
+ vsnprintf(p, sizeof(buf) - strlen(p), fmt, ap);
+ p+=strlen(p);
+ snprintf(p, sizeof(buf) - strlen(p), "\r\n");
+ p+=strlen(p);
+ sec_fprintf(stdout, "%s", buf);
+ fflush(stdout);
+ if (debug)
+ syslog(LOG_DEBUG, "<--- %s- ", buf);
+}
+
+void
+reply(int n, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(n, " ", fmt, ap);
+ delete_ftp_command();
+ va_end(ap);
+}
+
+void
+lreply(int n, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(n, "-", fmt, ap);
+ va_end(ap);
+}
+
+void
+nreply(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ int_reply(0, NULL, fmt, ap);
+ va_end(ap);
+}
+
+static void
+ack(char *s)
+{
+
+ reply(250, "%s command successful.", s);
+}
+
+void
+nack(char *s)
+{
+
+ reply(502, "%s command not implemented.", s);
+}
+
+/* ARGSUSED */
+void
+yyerror(char *s)
+{
+ char *cp;
+
+ if ((cp = strchr(cbuf,'\n')))
+ *cp = '\0';
+ reply(500, "'%s': command not understood.", cbuf);
+}
+
+void
+do_delete(char *name)
+{
+ struct stat st;
+
+ LOGCMD("delete", name);
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ if ((st.st_mode&S_IFMT) == S_IFDIR) {
+ if (rmdir(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+ goto done;
+ }
+ if (unlink(name) < 0) {
+ perror_reply(550, name);
+ return;
+ }
+done:
+ ack("DELE");
+}
+
+void
+cwd(char *path)
+{
+
+ if (chdir(path) < 0)
+ perror_reply(550, path);
+ else
+ ack("CWD");
+}
+
+void
+makedir(char *name)
+{
+
+ LOGCMD("mkdir", name);
+ if(guest && filename_check(name))
+ return;
+ if (mkdir(name, 0777) < 0)
+ perror_reply(550, name);
+ else{
+ if(guest)
+ chmod(name, 0700); /* guest has umask 777 */
+ reply(257, "MKD command successful.");
+ }
+}
+
+void
+removedir(char *name)
+{
+
+ LOGCMD("rmdir", name);
+ if (rmdir(name) < 0)
+ perror_reply(550, name);
+ else
+ ack("RMD");
+}
+
+void
+pwd(void)
+{
+ char path[MaxPathLen];
+ char *ret;
+
+ /* SunOS has a broken getcwd that does popen(pwd) (!!!), this
+ * failes miserably when running chroot
+ */
+ ret = getcwd(path, sizeof(path));
+ if (ret == NULL)
+ reply(550, "%s.", strerror(errno));
+ else
+ reply(257, "\"%s\" is current directory.", path);
+}
+
+char *
+renamefrom(char *name)
+{
+ struct stat st;
+
+ if (stat(name, &st) < 0) {
+ perror_reply(550, name);
+ return NULL;
+ }
+ reply(350, "File exists, ready for destination name");
+ return (name);
+}
+
+void
+renamecmd(char *from, char *to)
+{
+
+ LOGCMD2("rename", from, to);
+ if(guest && filename_check(to))
+ return;
+ if (rename(from, to) < 0)
+ perror_reply(550, "rename");
+ else
+ ack("RNTO");
+}
+
+static void
+dolog(struct sockaddr *sa, int len)
+{
+ getnameinfo_verified (sa, len, remotehost, sizeof(remotehost),
+ NULL, 0, 0);
+#ifdef HAVE_SETPROCTITLE
+ snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
+ setproctitle(proctitle);
+#endif /* HAVE_SETPROCTITLE */
+
+ if (logging) {
+ char data_addr[256];
+
+ if (inet_ntop (his_addr->sa_family,
+ socket_get_address(his_addr),
+ data_addr, sizeof(data_addr)) == NULL)
+ strlcpy (data_addr, "unknown address",
+ sizeof(data_addr));
+
+
+ syslog(LOG_INFO, "connection from %s(%s)",
+ remotehost,
+ data_addr);
+ }
+}
+
+/*
+ * Record logout in wtmp file
+ * and exit with supplied status.
+ */
+void
+dologout(int status)
+{
+ transflag = 0;
+ if (logged_in) {
+ seteuid((uid_t)0);
+ ftpd_logwtmp(ttyline, "", "");
+#ifdef KRB4
+ cond_kdestroy();
+#endif
+ }
+ /* beware of flushing buffers after a SIGPIPE */
+#ifdef XXX
+ exit(status);
+#else
+ _exit(status);
+#endif
+}
+
+void abor(void)
+{
+}
+
+static void
+myoob(int signo)
+{
+#if 0
+ char *cp;
+#endif
+
+ /* only process if transfer occurring */
+ if (!transflag)
+ return;
+
+ /* This is all XXX */
+ oobflag = 1;
+ /* if the command resulted in a new command,
+ parse that as well */
+ do{
+ yyparse();
+ } while(ftp_command);
+ oobflag = 0;
+
+#if 0
+ cp = tmpline;
+ if (ftpd_getline(cp, 7) == NULL) {
+ reply(221, "You could at least say goodbye.");
+ dologout(0);
+ }
+ upper(cp);
+ if (strcmp(cp, "ABOR\r\n") == 0) {
+ tmpline[0] = '\0';
+ reply(426, "Transfer aborted. Data connection closed.");
+ reply(226, "Abort successful");
+ longjmp(urgcatch, 1);
+ }
+ if (strcmp(cp, "STAT\r\n") == 0) {
+ if (file_size != (off_t) -1)
+ reply(213, "Status: %ld of %ld bytes transferred",
+ (long)byte_count,
+ (long)file_size);
+ else
+ reply(213, "Status: %ld bytes transferred"
+ (long)byte_count);
+ }
+#endif
+}
+
+/*
+ * Note: a response of 425 is not mentioned as a possible response to
+ * the PASV command in RFC959. However, it has been blessed as
+ * a legitimate response by Jon Postel in a telephone conversation
+ * with Rick Adams on 25 Jan 89.
+ */
+void
+pasv(void)
+{
+ int len;
+ char *p, *a;
+ struct sockaddr_in *sin;
+
+ if (ctrl_addr->sa_family != AF_INET) {
+ reply(425,
+ "You cannot do PASV with something that's not IPv4");
+ return;
+ }
+
+ pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (pdata < 0) {
+ perror_reply(425, "Can't open passive connection");
+ return;
+ }
+ pasv_addr->sa_family = ctrl_addr->sa_family;
+ socket_set_address_and_port (pasv_addr,
+ socket_get_address (ctrl_addr),
+ 0);
+ seteuid(0);
+ if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
+ seteuid(pw->pw_uid);
+ goto pasv_error;
+ }
+ seteuid(pw->pw_uid);
+ len = sizeof(pasv_addr_ss);
+ if (getsockname(pdata, pasv_addr, &len) < 0)
+ goto pasv_error;
+ if (listen(pdata, 1) < 0)
+ goto pasv_error;
+ sin = (struct sockaddr_in *)pasv_addr;
+ a = (char *) &sin->sin_addr;
+ p = (char *) &sin->sin_port;
+
+#define UC(b) (((int) b) & 0xff)
+
+ reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
+ UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
+ return;
+
+pasv_error:
+ close(pdata);
+ pdata = -1;
+ perror_reply(425, "Can't open passive connection");
+ return;
+}
+
+void
+epsv(char *proto)
+{
+ int len;
+
+ pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0);
+ if (pdata < 0) {
+ perror_reply(425, "Can't open passive connection");
+ return;
+ }
+ pasv_addr->sa_family = ctrl_addr->sa_family;
+ socket_set_address_and_port (pasv_addr,
+ socket_get_address (ctrl_addr),
+ 0);
+ seteuid(0);
+ if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) {
+ seteuid(pw->pw_uid);
+ goto pasv_error;
+ }
+ seteuid(pw->pw_uid);
+ len = sizeof(pasv_addr_ss);
+ if (getsockname(pdata, pasv_addr, &len) < 0)
+ goto pasv_error;
+ if (listen(pdata, 1) < 0)
+ goto pasv_error;
+
+ reply(229, "Entering Extended Passive Mode (|||%d|)",
+ ntohs(socket_get_port (pasv_addr)));
+ return;
+
+pasv_error:
+ close(pdata);
+ pdata = -1;
+ perror_reply(425, "Can't open passive connection");
+ return;
+}
+
+void
+eprt(char *str)
+{
+ char *end;
+ char sep;
+ int af;
+ int ret;
+ int port;
+
+ usedefault = 0;
+ if (pdata >= 0) {
+ close(pdata);
+ pdata = -1;
+ }
+
+ sep = *str++;
+ if (sep == '\0') {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ af = strtol (str, &end, 0);
+ if (af == 0 || *end != sep) {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ str = end + 1;
+ switch (af) {
+#ifdef HAVE_IPV6
+ case 2 :
+ data_dest->sa_family = AF_INET6;
+ break;
+#endif
+ case 1 :
+ data_dest->sa_family = AF_INET;
+ break;
+ default :
+ reply(522, "Network protocol %d not supported, use (1"
+#ifdef HAVE_IPV6
+ ",2"
+#endif
+ ")", af);
+ return;
+ }
+ end = strchr (str, sep);
+ if (end == NULL) {
+ reply(500, "Bad syntax in EPRT");
+ return;
+ }
+ *end = '\0';
+ ret = inet_pton (data_dest->sa_family, str,
+ socket_get_address (data_dest));
+
+ if (ret != 1) {
+ reply(500, "Bad address syntax in EPRT");
+ return;
+ }
+ str = end + 1;
+ port = strtol (str, &end, 0);
+ if (port == 0 || *end != sep) {
+ reply(500, "Bad port syntax in EPRT");
+ return;
+ }
+ socket_set_port (data_dest, htons(port));
+ reply(200, "EPRT command successful.");
+}
+
+/*
+ * Generate unique name for file with basename "local".
+ * The file named "local" is already known to exist.
+ * Generates failure reply on error.
+ */
+static char *
+gunique(char *local)
+{
+ static char new[MaxPathLen];
+ struct stat st;
+ int count;
+ char *cp;
+
+ cp = strrchr(local, '/');
+ if (cp)
+ *cp = '\0';
+ if (stat(cp ? local : ".", &st) < 0) {
+ perror_reply(553, cp ? local : ".");
+ return NULL;
+ }
+ if (cp)
+ *cp = '/';
+ for (count = 1; count < 100; count++) {
+ snprintf (new, sizeof(new), "%s.%d", local, count);
+ if (stat(new, &st) < 0)
+ return (new);
+ }
+ reply(452, "Unique file name cannot be created.");
+ return (NULL);
+}
+
+/*
+ * Format and send reply containing system error number.
+ */
+void
+perror_reply(int code, const char *string)
+{
+ reply(code, "%s: %s.", string, strerror(errno));
+}
+
+static char *onefile[] = {
+ "",
+ 0
+};
+
+void
+list_file(char *file)
+{
+ if(use_builtin_ls) {
+ FILE *dout;
+ dout = dataconn(file, -1, "w");
+ if (dout == NULL)
+ return;
+ set_buffer_size(fileno(dout), 0);
+ builtin_ls(dout, file);
+ reply(226, "Transfer complete.");
+ fclose(dout);
+ data = -1;
+ pdata = -1;
+ } else {
+#ifdef HAVE_LS_A
+ const char *cmd = "/bin/ls -lA -- %s";
+#else
+ const char *cmd = "/bin/ls -la -- %s";
+#endif
+ retrieve(cmd, file);
+ }
+}
+
+void
+send_file_list(char *whichf)
+{
+ struct stat st;
+ DIR *dirp = NULL;
+ struct dirent *dir;
+ FILE *dout = NULL;
+ char **dirlist, *dirname;
+ int simple = 0;
+ int freeglob = 0;
+ glob_t gl;
+ char buf[MaxPathLen];
+
+ if (strpbrk(whichf, "~{[*?") != NULL) {
+ int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ freeglob = 1;
+ if (glob(whichf, flags, 0, &gl)) {
+ reply(550, "not found");
+ goto out;
+ } else if (gl.gl_pathc == 0) {
+ errno = ENOENT;
+ perror_reply(550, whichf);
+ goto out;
+ }
+ dirlist = gl.gl_pathv;
+ } else {
+ onefile[0] = whichf;
+ dirlist = onefile;
+ simple = 1;
+ }
+
+ if (setjmp(urgcatch)) {
+ transflag = 0;
+ goto out;
+ }
+ while ((dirname = *dirlist++)) {
+ if (stat(dirname, &st) < 0) {
+ /*
+ * If user typed "ls -l", etc, and the client
+ * used NLST, do what the user meant.
+ */
+ if (dirname[0] == '-' && *dirlist == NULL &&
+ transflag == 0) {
+ retrieve("/bin/ls -- %s", dirname);
+ goto out;
+ }
+ perror_reply(550, whichf);
+ if (dout != NULL) {
+ fclose(dout);
+ transflag = 0;
+ data = -1;
+ pdata = -1;
+ }
+ goto out;
+ }
+
+ if (S_ISREG(st.st_mode)) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t)-1, "w");
+ if (dout == NULL)
+ goto out;
+ transflag++;
+ }
+ snprintf(buf, sizeof(buf), "%s%s\n", dirname,
+ type == TYPE_A ? "\r" : "");
+ sec_write(fileno(dout), buf, strlen(buf));
+ byte_count += strlen(dirname) + 1;
+ continue;
+ } else if (!S_ISDIR(st.st_mode))
+ continue;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ continue;
+
+ while ((dir = readdir(dirp)) != NULL) {
+ char nbuf[MaxPathLen];
+
+ if (!strcmp(dir->d_name, "."))
+ continue;
+ if (!strcmp(dir->d_name, ".."))
+ continue;
+
+ snprintf(nbuf, sizeof(nbuf), "%s/%s", dirname, dir->d_name);
+
+ /*
+ * We have to do a stat to insure it's
+ * not a directory or special file.
+ */
+ if (simple || (stat(nbuf, &st) == 0 &&
+ S_ISREG(st.st_mode))) {
+ if (dout == NULL) {
+ dout = dataconn("file list", (off_t)-1, "w");
+ if (dout == NULL)
+ goto out;
+ transflag++;
+ }
+ if(strncmp(nbuf, "./", 2) == 0)
+ snprintf(buf, sizeof(buf), "%s%s\n", nbuf +2,
+ type == TYPE_A ? "\r" : "");
+ else
+ snprintf(buf, sizeof(buf), "%s%s\n", nbuf,
+ type == TYPE_A ? "\r" : "");
+ sec_write(fileno(dout), buf, strlen(buf));
+ byte_count += strlen(nbuf) + 1;
+ }
+ }
+ closedir(dirp);
+ }
+ if (dout == NULL)
+ reply(550, "No files found.");
+ else if (ferror(dout) != 0)
+ perror_reply(550, "Data connection");
+ else
+ reply(226, "Transfer complete.");
+
+ transflag = 0;
+ if (dout != NULL){
+ sec_write(fileno(dout), buf, 0); /* XXX flush */
+
+ fclose(dout);
+ }
+ data = -1;
+ pdata = -1;
+out:
+ if (freeglob) {
+ freeglob = 0;
+ globfree(&gl);
+ }
+}
+
+
+int
+find(char *pattern)
+{
+ char line[1024];
+ FILE *f;
+
+ snprintf(line, sizeof(line),
+ "/bin/locate -d %s -- %s",
+ ftp_rooted("/etc/locatedb"),
+ pattern);
+ f = ftpd_popen(line, "r", 1, 1);
+ if(f == NULL){
+ perror_reply(550, "/bin/locate");
+ return 1;
+ }
+ lreply(200, "Output from find.");
+ while(fgets(line, sizeof(line), f)){
+ if(line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = 0;
+ nreply("%s", line);
+ }
+ reply(200, "Done");
+ ftpd_pclose(f);
+ return 0;
+}
+
diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h b/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h
new file mode 100644
index 0000000..5cb4904
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ftpd_locl.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 1998, 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: ftpd_locl.h,v 1.9 1999/12/02 16:58:30 joda Exp $ */
+
+#ifndef __ftpd_locl_h__
+#define __ftpd_locl_h__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * FTP server.
+ */
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#endif
+#ifdef HAVE_NETINET_IP_H
+#include <netinet/ip.h>
+#endif
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <arpa/ftp.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_TELNET_H
+#include <arpa/telnet.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <glob.h>
+#include <limits.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#include <fnmatch.h>
+
+#ifdef HAVE_BSD_BSD_H
+#include <bsd/bsd.h>
+#endif
+
+#include <err.h>
+
+#include "pathnames.h"
+#include "extern.h"
+#include "common.h"
+
+#include "security.h"
+
+#include "roken.h"
+
+#ifdef KRB4
+#include <krb.h>
+#include <kafs.h>
+#endif
+
+#ifdef OTP
+#include <otp.h>
+#endif
+
+#ifdef SOCKS
+#include <socks.h>
+extern int LIBPREFIX(fclose) (FILE *);
+#endif
+
+/* SunOS doesn't have any declaration of fclose */
+
+int fclose(FILE *stream);
+
+int yyparse();
+
+#ifndef LOG_FTP
+#define LOG_FTP LOG_DAEMON
+#endif
+
+#endif /* __ftpd_locl_h__ */
diff --git a/crypto/heimdal/appl/ftp/ftpd/ftpusers.5 b/crypto/heimdal/appl/ftp/ftpd/ftpusers.5
new file mode 100644
index 0000000..dfd66f9
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ftpusers.5
@@ -0,0 +1,38 @@
+.\" $Id: ftpusers.5,v 1.2 1997/05/07 20:11:11 joda Exp $
+.\"
+.Dd May 7, 1997
+.Dt FTPUSERS 5
+.Os KTH-KRB
+.Sh NAME
+.Pa /etc/ftpusers
+.Nd
+FTP access list file.
+.Sh DESCRIPTION
+.Pa /etc/ftpusers
+contains a list of users that should be allowed or denied FTP
+access. Each line contains a user, optionally followed by
+.Dq allow
+(anything but
+.Dq allow
+is ignored). The semi-user
+.Dq *
+matches any user. Users that has an explicit
+.Dq allow ,
+or that does not match any line, are allowed access. Anyone else is
+denied access.
+
+Note that this is compatible with the old format, where this file
+contained a list of users that should be denied access.
+.Sh EXAMPLES
+This will deny anyone but
+.Dq foo
+and
+.Dq bar
+to use FTP:
+.Bd -literal
+foo allow
+bar allow
+*
+.Ed
+.Sh SEE ALSO
+.Xr ftpd 8
diff --git a/crypto/heimdal/appl/ftp/ftpd/gss_userok.c b/crypto/heimdal/appl/ftp/ftpd/gss_userok.c
new file mode 100644
index 0000000..28e3596
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/gss_userok.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "ftpd_locl.h"
+#include <gssapi.h>
+#include <krb5.h>
+
+RCSID("$Id: gss_userok.c,v 1.2 1999/12/02 16:58:31 joda Exp $");
+
+/* XXX a bit too much of krb5 dependency here...
+ What is the correct way to do this?
+ */
+
+extern krb5_context gssapi_krb5_context;
+
+/* XXX sync with gssapi.c */
+struct gss_data {
+ gss_ctx_id_t context_hdl;
+ char *client_name;
+};
+
+int gss_userok(void*, char*); /* to keep gcc happy */
+
+int
+gss_userok(void *app_data, char *username)
+{
+ struct gss_data *data = app_data;
+ if(gssapi_krb5_context) {
+ krb5_principal client;
+ krb5_error_code ret;
+ ret = krb5_parse_name(gssapi_krb5_context, data->client_name, &client);
+ if(ret)
+ return 1;
+ ret = krb5_kuserok(gssapi_krb5_context, client, username);
+ krb5_free_principal(gssapi_krb5_context, client);
+ return !ret;
+ }
+ return 1;
+}
diff --git a/crypto/heimdal/appl/ftp/ftpd/kauth.c b/crypto/heimdal/appl/ftp/ftpd/kauth.c
new file mode 100644
index 0000000..dad4de5
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/kauth.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+#include "ftpd_locl.h"
+
+RCSID("$Id: kauth.c,v 1.25 1999/12/02 16:58:31 joda Exp $");
+
+static KTEXT_ST cip;
+static unsigned int lifetime;
+static time_t local_time;
+
+static krb_principal pr;
+
+static int do_destroy_tickets = 1;
+
+static int
+save_tkt(const char *user,
+ const char *instance,
+ const char *realm,
+ const void *arg,
+ key_proc_t key_proc,
+ KTEXT *cipp)
+{
+ local_time = time(0);
+ memmove(&cip, *cipp, sizeof(cip));
+ return -1;
+}
+
+static int
+store_ticket(KTEXT cip)
+{
+ char *ptr;
+ des_cblock session;
+ krb_principal sp;
+ unsigned char kvno;
+ KTEXT_ST tkt;
+ int left = cip->length;
+ int len;
+ int kerror;
+
+ ptr = (char *) cip->dat;
+
+ /* extract session key */
+ memmove(session, ptr, 8);
+ ptr += 8;
+ left -= 8;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's name */
+ strlcpy(sp.name, ptr, sizeof(sp.name));
+ ptr += len + 1;
+ left -= len + 1;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's instance */
+ strlcpy(sp.instance, ptr, sizeof(sp.instance));
+ ptr += len + 1;
+ left -= len + 1;
+
+ len = strnlen(ptr, left);
+ if (len == left)
+ return(INTK_BADPW);
+
+ /* extract server's realm */
+ strlcpy(sp.realm, ptr, sizeof(sp.realm));
+ ptr += len + 1;
+ left -= len + 1;
+
+ if(left < 3)
+ return INTK_BADPW;
+ /* extract ticket lifetime, server key version, ticket length */
+ /* be sure to avoid sign extension on lifetime! */
+ lifetime = (unsigned char) ptr[0];
+ kvno = (unsigned char) ptr[1];
+ tkt.length = (unsigned char) ptr[2];
+ ptr += 3;
+ left -= 3;
+
+ if (tkt.length > left)
+ return(INTK_BADPW);
+
+ /* extract ticket itself */
+ memmove(tkt.dat, ptr, tkt.length);
+ ptr += tkt.length;
+ left -= tkt.length;
+
+ /* Here is where the time should be verified against the KDC.
+ * Unfortunately everything is sent in host byte order (receiver
+ * makes wrong) , and at this stage there is no way for us to know
+ * which byteorder the KDC has. So we simply ignore the time,
+ * there are no security risks with this, the only thing that can
+ * happen is that we might receive a replayed ticket, which could
+ * at most be useless.
+ */
+
+#if 0
+ /* check KDC time stamp */
+ {
+ time_t kdc_time;
+
+ memmove(&kdc_time, ptr, sizeof(kdc_time));
+ if (swap_bytes) swap_u_long(kdc_time);
+
+ ptr += 4;
+
+ if (abs((int)(local_time - kdc_time)) > CLOCK_SKEW) {
+ return(RD_AP_TIME); /* XXX should probably be better
+ code */
+ }
+ }
+#endif
+
+ /* initialize ticket cache */
+
+ if (tf_create(TKT_FILE) != KSUCCESS)
+ return(INTK_ERR);
+
+ if (tf_put_pname(pr.name) != KSUCCESS ||
+ tf_put_pinst(pr.instance) != KSUCCESS) {
+ tf_close();
+ return(INTK_ERR);
+ }
+
+
+ kerror = tf_save_cred(sp.name, sp.instance, sp.realm, session,
+ lifetime, kvno, &tkt, local_time);
+ tf_close();
+
+ return(kerror);
+}
+
+void
+kauth(char *principal, char *ticket)
+{
+ char *p;
+ int ret;
+
+ if(get_command_prot() != prot_private) {
+ reply(500, "Request denied (bad protection level)");
+ return;
+ }
+ ret = krb_parse_name(principal, &pr);
+ if(ret){
+ reply(500, "Bad principal: %s.", krb_get_err_text(ret));
+ return;
+ }
+ if(pr.realm[0] == 0)
+ krb_get_lrealm(pr.realm, 1);
+
+ if(ticket){
+ cip.length = base64_decode(ticket, &cip.dat);
+ if(cip.length == -1){
+ reply(500, "Failed to decode data.");
+ return;
+ }
+ ret = store_ticket(&cip);
+ if(ret){
+ reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
+ memset(&cip, 0, sizeof(cip));
+ return;
+ }
+ do_destroy_tickets = 1;
+
+ if(k_hasafs())
+ krb_afslog(0, 0);
+ reply(200, "Tickets will be destroyed on exit.");
+ return;
+ }
+
+ ret = krb_get_in_tkt (pr.name,
+ pr.instance,
+ pr.realm,
+ KRB_TICKET_GRANTING_TICKET,
+ pr.realm,
+ DEFAULT_TKT_LIFE,
+ NULL, save_tkt, NULL);
+ if(ret != INTK_BADPW){
+ reply(500, "Kerberos error: %s.", krb_get_err_text(ret));
+ return;
+ }
+ if(base64_encode(cip.dat, cip.length, &p) < 0) {
+ reply(500, "Out of memory while base64-encoding.");
+ return;
+ }
+ reply(300, "P=%s T=%s", krb_unparse_name(&pr), p);
+ free(p);
+ memset(&cip, 0, sizeof(cip));
+}
+
+
+static char *
+short_date(int32_t dp)
+{
+ char *cp;
+ time_t t = (time_t)dp;
+
+ if (t == (time_t)(-1L)) return "*** Never *** ";
+ cp = ctime(&t) + 4;
+ cp[15] = '\0';
+ return (cp);
+}
+
+void
+klist(void)
+{
+ int err;
+
+ char *file = tkt_string();
+
+ krb_principal pr;
+
+ char buf1[128], buf2[128];
+ int header = 1;
+ CREDENTIALS c;
+
+
+
+ err = tf_init(file, R_TKT_FIL);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+ tf_close();
+
+ /*
+ * We must find the realm of the ticket file here before calling
+ * tf_init because since the realm of the ticket file is not
+ * really stored in the principal section of the file, the
+ * routine we use must itself call tf_init and tf_close.
+ */
+ err = krb_get_tf_realm(file, pr.realm);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ err = tf_init(file, R_TKT_FIL);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ err = tf_get_pname(pr.name);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+ err = tf_get_pinst(pr.instance);
+ if(err != KSUCCESS){
+ reply(500, "%s", krb_get_err_text(err));
+ return;
+ }
+
+ /*
+ * You may think that this is the obvious place to get the
+ * realm of the ticket file, but it can't be done here as the
+ * routine to do this must open the ticket file. This is why
+ * it was done before tf_init.
+ */
+
+ lreply(200, "Ticket file: %s", tkt_string());
+
+ lreply(200, "Principal: %s", krb_unparse_name(&pr));
+ while ((err = tf_get_cred(&c)) == KSUCCESS) {
+ if (header) {
+ lreply(200, "%-15s %-15s %s",
+ " Issued", " Expires", " Principal (kvno)");
+ header = 0;
+ }
+ strlcpy(buf1, short_date(c.issue_date), sizeof(buf1));
+ c.issue_date = krb_life_to_time(c.issue_date, c.lifetime);
+ if (time(0) < (unsigned long) c.issue_date)
+ strlcpy(buf2, short_date(c.issue_date), sizeof(buf2));
+ else
+ strlcpy(buf2, ">>> Expired <<< ", sizeof(buf2));
+ lreply(200, "%s %s %s (%d)", buf1, buf2,
+ krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno);
+ }
+ if (header && err == EOF) {
+ lreply(200, "No tickets in file.");
+ }
+ reply(200, " ");
+}
+
+/*
+ * Only destroy if we created the tickets
+ */
+
+void
+cond_kdestroy(void)
+{
+ if (do_destroy_tickets)
+ dest_tkt();
+ afsunlog();
+}
+
+void
+kdestroy(void)
+{
+ dest_tkt();
+ afsunlog();
+ reply(200, "Tickets destroyed");
+}
+
+void
+krbtkfile(const char *tkfile)
+{
+ do_destroy_tickets = 0;
+ krb_set_tkt_string(tkfile);
+ reply(200, "Using ticket file %s", tkfile);
+}
+
+void
+afslog(const char *cell)
+{
+ if(k_hasafs()) {
+ krb_afslog(cell, 0);
+ reply(200, "afslog done");
+ } else {
+ reply(200, "no AFS present");
+ }
+}
+
+void
+afsunlog(void)
+{
+ if(k_hasafs())
+ k_unlog();
+}
diff --git a/crypto/heimdal/appl/ftp/ftpd/logwtmp.c b/crypto/heimdal/appl/ftp/ftpd/logwtmp.c
new file mode 100644
index 0000000..019cc2d
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/logwtmp.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: logwtmp.c,v 1.14 1999/12/02 16:58:31 joda Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#endif
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif
+#include "extern.h"
+
+#ifndef WTMP_FILE
+#ifdef _PATH_WTMP
+#define WTMP_FILE _PATH_WTMP
+#else
+#define WTMP_FILE "/var/adm/wtmp"
+#endif
+#endif
+
+void
+ftpd_logwtmp(char *line, char *name, char *host)
+{
+ static int init = 0;
+ static int fd;
+#ifdef WTMPX_FILE
+ static int fdx;
+#endif
+ struct utmp ut;
+#ifdef WTMPX_FILE
+ struct utmpx utx;
+#endif
+
+ memset(&ut, 0, sizeof(struct utmp));
+#ifdef HAVE_STRUCT_UTMP_UT_TYPE
+ if(name[0])
+ ut.ut_type = USER_PROCESS;
+ else
+ ut.ut_type = DEAD_PROCESS;
+#endif
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ strncpy(ut.ut_name, name, sizeof(ut.ut_name));
+#ifdef HAVE_STRUCT_UTMP_UT_PID
+ ut.ut_pid = getpid();
+#endif
+#ifdef HAVE_STRUCT_UTMP_UT_HOST
+ strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+#endif
+ ut.ut_time = time(NULL);
+
+#ifdef WTMPX_FILE
+ strncpy(utx.ut_line, line, sizeof(utx.ut_line));
+ strncpy(utx.ut_user, name, sizeof(utx.ut_user));
+ strncpy(utx.ut_host, host, sizeof(utx.ut_host));
+#ifdef HAVE_STRUCT_UTMPX_UT_SYSLEN
+ utx.ut_syslen = strlen(host) + 1;
+ if (utx.ut_syslen > sizeof(utx.ut_host))
+ utx.ut_syslen = sizeof(utx.ut_host);
+#endif
+ {
+ struct timeval tv;
+
+ gettimeofday (&tv, 0);
+ utx.ut_tv.tv_sec = tv.tv_sec;
+ utx.ut_tv.tv_usec = tv.tv_usec;
+ }
+
+ if(name[0])
+ utx.ut_type = USER_PROCESS;
+ else
+ utx.ut_type = DEAD_PROCESS;
+#endif
+
+ if(!init){
+ fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0);
+#ifdef WTMPX_FILE
+ fdx = open(WTMPX_FILE, O_WRONLY|O_APPEND, 0);
+#endif
+ init = 1;
+ }
+ if(fd >= 0) {
+ write(fd, &ut, sizeof(struct utmp)); /* XXX */
+#ifdef WTMPX_FILE
+ write(fdx, &utx, sizeof(struct utmpx));
+#endif
+ }
+}
diff --git a/crypto/heimdal/appl/ftp/ftpd/ls.c b/crypto/heimdal/appl/ftp/ftpd/ls.c
new file mode 100644
index 0000000..2c85487
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/ls.c
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */
+
+#include "ftpd_locl.h"
+
+RCSID("$Id: ls.c,v 1.14 2000/01/05 13:48:58 joda Exp $");
+
+struct fileinfo {
+ struct stat st;
+ int inode;
+ int bsize;
+ char mode[11];
+ int n_link;
+ char *user;
+ char *group;
+ char *size;
+ char *major;
+ char *minor;
+ char *date;
+ char *filename;
+ char *link;
+};
+
+static void
+free_fileinfo(struct fileinfo *f)
+{
+ free(f->user);
+ free(f->group);
+ free(f->size);
+ free(f->major);
+ free(f->minor);
+ free(f->date);
+ free(f->filename);
+ free(f->link);
+}
+
+#define LS_DIRS 1
+#define LS_IGNORE_DOT 2
+#define LS_SORT_MODE 12
+#define SORT_MODE(f) ((f) & LS_SORT_MODE)
+#define LS_SORT_NAME 4
+#define LS_SORT_MTIME 8
+#define LS_SORT_SIZE 12
+#define LS_SORT_REVERSE 16
+
+#define LS_SIZE 32
+#define LS_INODE 64
+
+#ifndef S_ISTXT
+#define S_ISTXT S_ISVTX
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode) (((mode) & _S_IFMT) == S_IFSOCK)
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK)
+#endif
+
+static void
+make_fileinfo(const char *filename, struct fileinfo *file, int flags)
+{
+ char buf[128];
+ struct stat *st = &file->st;
+
+ file->inode = st->st_ino;
+#ifdef S_BLKSIZE
+ file->bsize = st->st_blocks * S_BLKSIZE / 1024;
+#else
+ file->bsize = st->st_blocks * 512 / 1024;
+#endif
+
+ if(S_ISDIR(st->st_mode))
+ file->mode[0] = 'd';
+ else if(S_ISCHR(st->st_mode))
+ file->mode[0] = 'c';
+ else if(S_ISBLK(st->st_mode))
+ file->mode[0] = 'b';
+ else if(S_ISREG(st->st_mode))
+ file->mode[0] = '-';
+ else if(S_ISFIFO(st->st_mode))
+ file->mode[0] = 'p';
+ else if(S_ISLNK(st->st_mode))
+ file->mode[0] = 'l';
+ else if(S_ISSOCK(st->st_mode))
+ file->mode[0] = 's';
+#ifdef S_ISWHT
+ else if(S_ISWHT(st->st_mode))
+ file->mode[0] = 'w';
+#endif
+ else
+ file->mode[0] = '?';
+ {
+ char *x[] = { "---", "--x", "-w-", "-wx",
+ "r--", "r-x", "rw-", "rwx" };
+ strcpy(file->mode + 1, x[(st->st_mode & S_IRWXU) >> 6]);
+ strcpy(file->mode + 4, x[(st->st_mode & S_IRWXG) >> 3]);
+ strcpy(file->mode + 7, x[(st->st_mode & S_IRWXO) >> 0]);
+ if((st->st_mode & S_ISUID)) {
+ if((st->st_mode & S_IXUSR))
+ file->mode[3] = 's';
+ else
+ file->mode[3] = 'S';
+ }
+ if((st->st_mode & S_ISGID)) {
+ if((st->st_mode & S_IXGRP))
+ file->mode[6] = 's';
+ else
+ file->mode[6] = 'S';
+ }
+ if((st->st_mode & S_ISTXT)) {
+ if((st->st_mode & S_IXOTH))
+ file->mode[9] = 't';
+ else
+ file->mode[9] = 'T';
+ }
+ }
+ file->n_link = st->st_nlink;
+ {
+ struct passwd *pwd;
+ pwd = getpwuid(st->st_uid);
+ if(pwd == NULL)
+ asprintf(&file->user, "%u", (unsigned)st->st_uid);
+ else
+ file->user = strdup(pwd->pw_name);
+ }
+ {
+ struct group *grp;
+ grp = getgrgid(st->st_gid);
+ if(grp == NULL)
+ asprintf(&file->group, "%u", (unsigned)st->st_gid);
+ else
+ file->group = strdup(grp->gr_name);
+ }
+
+ if(S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
+#if defined(major) && defined(minor)
+ asprintf(&file->major, "%u", (unsigned)major(st->st_rdev));
+ asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev));
+#else
+ /* Don't want to use the DDI/DKI crap. */
+ asprintf(&file->major, "%u", (unsigned)st->st_rdev);
+ asprintf(&file->minor, "%u", 0);
+#endif
+ } else
+ asprintf(&file->size, "%lu", (unsigned long)st->st_size);
+
+ {
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&st->st_mtime);
+ if((t - st->st_mtime > 6*30*24*60*60) ||
+ (st->st_mtime - t > 6*30*24*60*60))
+ strftime(buf, sizeof(buf), "%b %e %Y", tm);
+ else
+ strftime(buf, sizeof(buf), "%b %e %H:%M", tm);
+ file->date = strdup(buf);
+ }
+ {
+ const char *p = strrchr(filename, '/');
+ if(p)
+ p++;
+ else
+ p = filename;
+ file->filename = strdup(p);
+ }
+ if(S_ISLNK(st->st_mode)) {
+ int n;
+ n = readlink((char *)filename, buf, sizeof(buf));
+ if(n >= 0) {
+ buf[n] = '\0';
+ file->link = strdup(buf);
+ } else
+ warn("%s: readlink", filename);
+ }
+}
+
+static void
+print_file(FILE *out,
+ int flags,
+ struct fileinfo *f,
+ int max_inode,
+ int max_bsize,
+ int max_n_link,
+ int max_user,
+ int max_group,
+ int max_size,
+ int max_major,
+ int max_minor,
+ int max_date)
+{
+ if(f->filename == NULL)
+ return;
+
+ if(flags & LS_INODE) {
+ sec_fprintf2(out, "%*d", max_inode, f->inode);
+ sec_fprintf2(out, " ");
+ }
+ if(flags & LS_SIZE) {
+ sec_fprintf2(out, "%*d", max_bsize, f->bsize);
+ sec_fprintf2(out, " ");
+ }
+ sec_fprintf2(out, "%s", f->mode);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%*d", max_n_link, f->n_link);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%-*s", max_user, f->user);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%-*s", max_group, f->group);
+ sec_fprintf2(out, " ");
+ if(f->major != NULL && f->minor != NULL)
+ sec_fprintf2(out, "%*s, %*s", max_major, f->major, max_minor, f->minor);
+ else
+ sec_fprintf2(out, "%*s", max_size, f->size);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%*s", max_date, f->date);
+ sec_fprintf2(out, " ");
+ sec_fprintf2(out, "%s", f->filename);
+ if(f->link)
+ sec_fprintf2(out, " -> %s", f->link);
+ sec_fprintf2(out, "\r\n");
+}
+
+static int
+compare_filename(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return strcmp(a->filename, b->filename);
+}
+
+static int
+compare_mtime(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return a->st.st_mtime - b->st.st_mtime;
+}
+
+static int
+compare_size(struct fileinfo *a, struct fileinfo *b)
+{
+ if(a->filename == NULL)
+ return 1;
+ if(b->filename == NULL)
+ return -1;
+ return a->st.st_size - b->st.st_size;
+}
+
+static void
+list_dir(FILE *out, const char *directory, int flags);
+
+static int
+log10(int num)
+{
+ int i = 1;
+ while(num > 10) {
+ i++;
+ num /= 10;
+ }
+ return i;
+}
+
+/*
+ * Operate as lstat but fake up entries for AFS mount points so we don't
+ * have to fetch them.
+ */
+
+static int
+lstat_file (const char *file, struct stat *sb)
+{
+#ifdef KRB4
+ if (k_hasafs()
+ && strcmp(file, ".")
+ && strcmp(file, ".."))
+ {
+ struct ViceIoctl a_params;
+ char *last;
+ char *path_bkp;
+ static ino_t ino_counter = 0, ino_last = 0;
+ int ret;
+ const int maxsize = 2048;
+
+ path_bkp = strdup (file);
+ if (path_bkp == NULL)
+ return -1;
+
+ a_params.out = malloc (maxsize);
+ if (a_params.out == NULL) {
+ free (path_bkp);
+ return -1;
+ }
+
+ /* If path contains more than the filename alone - split it */
+
+ last = strrchr (path_bkp, '/');
+ if (last != NULL) {
+ *last = '\0';
+ a_params.in = last + 1;
+ } else
+ a_params.in = (char *)file;
+
+ a_params.in_size = strlen (a_params.in) + 1;
+ a_params.out_size = maxsize;
+
+ ret = k_pioctl (last ? path_bkp : "." ,
+ VIOC_AFS_STAT_MT_PT, &a_params, 0);
+ free (a_params.out);
+ if (ret < 0) {
+ free (path_bkp);
+
+ if (errno != EINVAL)
+ return ret;
+ else
+ /* if we get EINVAL this is probably not a mountpoint */
+ return lstat (file, sb);
+ }
+
+ /*
+ * wow this was a mountpoint, lets cook the struct stat
+ * use . as a prototype
+ */
+
+ ret = lstat (path_bkp, sb);
+ free (path_bkp);
+ if (ret < 0)
+ return ret;
+
+ if (ino_last == sb->st_ino)
+ ino_counter++;
+ else {
+ ino_last = sb->st_ino;
+ ino_counter = 0;
+ }
+ sb->st_ino += ino_counter;
+ sb->st_nlink = 3;
+
+ return 0;
+ }
+#endif /* KRB4 */
+ return lstat (file, sb);
+}
+
+static void
+list_files(FILE *out, const char **files, int n_files, int flags)
+{
+ struct fileinfo *fi;
+ int i;
+
+ fi = calloc(n_files, sizeof(*fi));
+ if (fi == NULL) {
+ sec_fprintf2(out, "ouf of memory\r\n");
+ return;
+ }
+ for(i = 0; i < n_files; i++) {
+ if(lstat_file(files[i], &fi[i].st) < 0) {
+ sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno));
+ fi[i].filename = NULL;
+ } else {
+ if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) {
+ if(n_files > 1)
+ sec_fprintf2(out, "%s:\r\n", files[i]);
+ list_dir(out, files[i], flags);
+ } else {
+ make_fileinfo(files[i], &fi[i], flags);
+ }
+ }
+ }
+ switch(SORT_MODE(flags)) {
+ case LS_SORT_NAME:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_filename);
+ break;
+ case LS_SORT_MTIME:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_mtime);
+ break;
+ case LS_SORT_SIZE:
+ qsort(fi, n_files, sizeof(*fi),
+ (int (*)(const void*, const void*))compare_size);
+ break;
+ }
+ {
+ int max_inode = 0;
+ int max_bsize = 0;
+ int max_n_link = 0;
+ int max_user = 0;
+ int max_group = 0;
+ int max_size = 0;
+ int max_major = 0;
+ int max_minor = 0;
+ int max_date = 0;
+ for(i = 0; i < n_files; i++) {
+ if(fi[i].filename == NULL)
+ continue;
+ if(fi[i].inode > max_inode)
+ max_inode = fi[i].inode;
+ if(fi[i].bsize > max_bsize)
+ max_bsize = fi[i].bsize;
+ if(fi[i].n_link > max_n_link)
+ max_n_link = fi[i].n_link;
+ if(strlen(fi[i].user) > max_user)
+ max_user = strlen(fi[i].user);
+ if(strlen(fi[i].group) > max_group)
+ max_group = strlen(fi[i].group);
+ if(fi[i].major != NULL && strlen(fi[i].major) > max_major)
+ max_major = strlen(fi[i].major);
+ if(fi[i].minor != NULL && strlen(fi[i].minor) > max_minor)
+ max_minor = strlen(fi[i].minor);
+ if(fi[i].size != NULL && strlen(fi[i].size) > max_size)
+ max_size = strlen(fi[i].size);
+ if(strlen(fi[i].date) > max_date)
+ max_date = strlen(fi[i].date);
+ }
+ if(max_size < max_major + max_minor + 2)
+ max_size = max_major + max_minor + 2;
+ else if(max_size - max_minor - 2 > max_major)
+ max_major = max_size - max_minor - 2;
+ max_inode = log10(max_inode);
+ max_bsize = log10(max_bsize);
+ max_n_link = log10(max_n_link);
+
+ if(flags & LS_SORT_REVERSE)
+ for(i = n_files - 1; i >= 0; i--)
+ print_file(out,
+ flags,
+ &fi[i],
+ max_inode,
+ max_bsize,
+ max_n_link,
+ max_user,
+ max_group,
+ max_size,
+ max_major,
+ max_minor,
+ max_date);
+ else
+ for(i = 0; i < n_files; i++)
+ print_file(out,
+ flags,
+ &fi[i],
+ max_inode,
+ max_bsize,
+ max_n_link,
+ max_user,
+ max_group,
+ max_size,
+ max_major,
+ max_minor,
+ max_date);
+ for(i = 0; i < n_files; i++)
+ free_fileinfo(&fi[i]);
+ free(fi);
+ }
+}
+
+static void
+free_files (char **files, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ free (files[i]);
+ free (files);
+}
+
+static void
+list_dir(FILE *out, const char *directory, int flags)
+{
+ DIR *d = opendir(directory);
+ struct dirent *ent;
+ char **files = NULL;
+ int n_files = 0;
+
+ if(d == NULL) {
+ sec_fprintf2(out, "%s: %s\r\n", directory, strerror(errno));
+ return;
+ }
+ while((ent = readdir(d)) != NULL) {
+ void *tmp;
+
+ if(ent->d_name[0] == '.') {
+ if (flags & LS_IGNORE_DOT)
+ continue;
+ if (ent->d_name[1] == 0) /* Ignore . */
+ continue;
+ if (ent->d_name[1] == '.' && ent->d_name[2] == 0) /* Ignore .. */
+ continue;
+ }
+ tmp = realloc(files, (n_files + 1) * sizeof(*files));
+ if (tmp == NULL) {
+ sec_fprintf2(out, "%s: out of memory\r\n", directory);
+ free_files (files, n_files);
+ closedir (d);
+ return;
+ }
+ files = tmp;
+ asprintf(&files[n_files], "%s/%s", directory, ent->d_name);
+ if (files[n_files] == NULL) {
+ sec_fprintf2(out, "%s: out of memory\r\n", directory);
+ free_files (files, n_files);
+ closedir (d);
+ return;
+ }
+ ++n_files;
+ }
+ closedir(d);
+ list_files(out, (const char**)files, n_files, flags | LS_DIRS);
+}
+
+void
+builtin_ls(FILE *out, const char *file)
+{
+ int flags = LS_SORT_NAME;
+
+ if(*file == '-') {
+ const char *p;
+ for(p = file + 1; *p; p++) {
+ switch(*p) {
+ case 'a':
+ case 'A':
+ flags &= ~LS_IGNORE_DOT;
+ break;
+ case 'C':
+ break;
+ case 'd':
+ flags |= LS_DIRS;
+ break;
+ case 'f':
+ flags = (flags & ~LS_SORT_MODE);
+ break;
+ case 'i':
+ flags |= flags | LS_INODE;
+ break;
+ case 'l':
+ break;
+ case 't':
+ flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME;
+ break;
+ case 's':
+ flags |= LS_SIZE;
+ break;
+ case 'S':
+ flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE;
+ break;
+ case 'r':
+ flags |= LS_SORT_REVERSE;
+ break;
+ }
+ }
+ file = ".";
+ }
+ list_files(out, &file, 1, flags);
+ sec_fflush(out);
+}
diff --git a/crypto/heimdal/appl/ftp/ftpd/pathnames.h b/crypto/heimdal/appl/ftp/ftpd/pathnames.h
new file mode 100644
index 0000000..ff2041b
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/pathnames.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1989, 1993
+ * 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _PATH_NOLOGIN
+#define _PATH_NOLOGIN "/etc/nologin"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#define _PATH_FTPUSERS "/etc/ftpusers"
+#define _PATH_FTPCHROOT "/etc/ftpchroot"
+#define _PATH_FTPWELCOME "/etc/ftpwelcome"
+#define _PATH_FTPLOGINMESG "/etc/motd"
+
+#define _PATH_ISSUE "/etc/issue"
+#define _PATH_ISSUE_NET "/etc/issue.net"
diff --git a/crypto/heimdal/appl/ftp/ftpd/popen.c b/crypto/heimdal/appl/ftp/ftpd/popen.c
new file mode 100644
index 0000000..5f36813
--- /dev/null
+++ b/crypto/heimdal/appl/ftp/ftpd/popen.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1988, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$Id: popen.c,v 1.19 1999/09/16 20:38:45 assar Exp $");
+#endif
+
+#include <sys/types.h>
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <glob.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+
+#include <roken.h>
+
+/*
+ * Special version of popen which avoids call to shell. This ensures
+ * no one may create a pipe to a hidden program as a side effect of a
+ * list or dir command.
+ */
+static int *pids;
+static int fds;
+
+extern int dochroot;
+
+/* return path prepended with ~ftp if that file exists, otherwise
+ * return path unchanged
+ */
+
+const char *
+ftp_rooted(const char *path)
+{
+ static char home[MaxPathLen] = "";
+ static char newpath[MaxPathLen];
+ struct passwd *pwd;
+
+ if(!home[0])
+ if((pwd = k_getpwnam("ftp")))
+ strlcpy(home, pwd->pw_dir, sizeof(home));
+ snprintf(newpath, sizeof(newpath), "%s/%s", home, path);
+ if(access(newpath, X_OK))
+ strlcpy(newpath, path, sizeof(newpath));
+ return newpath;
+}
+
+
+FILE *
+ftpd_popen(char *program, char *type, int do_stderr, int no_glob)
+{
+ char *cp;
+ FILE *iop;
+ int argc, gargc, pdes[2], pid;
+ char **pop, *argv[100], *gargv[1000];
+ char *foo;
+
+ if (strcmp(type, "r") && strcmp(type, "w"))
+ return (NULL);
+
+ if (!pids) {
+
+ /* This function is ugly and should be rewritten, in
+ * modern unices there is no such thing as a maximum
+ * filedescriptor.
+ */
+
+ fds = getdtablesize();
+ pids = (int*)calloc(fds, sizeof(int));
+ if(!pids)
+ return NULL;
+ }
+ if (pipe(pdes) < 0)
+ return (NULL);
+
+ /* break up string into pieces */
+ foo = NULL;
+ for (argc = 0, cp = program;; cp = NULL) {
+ if (!(argv[argc++] = strtok_r(cp, " \t\n", &foo)))
+ break;
+ }
+
+ gargv[0] = (char*)ftp_rooted(argv[0]);
+ /* glob each piece */
+ for (gargc = argc = 1; argv[argc]; argc++) {
+ glob_t gl;
+ int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
+
+ memset(&gl, 0, sizeof(gl));
+ if (no_glob || glob(argv[argc], flags, NULL, &gl))
+ gargv[gargc++] = strdup(argv[argc]);
+ else
+ for (pop = gl.gl_pathv; *pop; pop++)
+ gargv[gargc++] = strdup(*pop);
+ globfree(&gl);
+ }
+ gargv[gargc] = NULL;
+
+ iop = NULL;
+ switch(pid = fork()) {
+ case -1: /* error */
+ close(pdes[0]);
+ close(pdes[1]);
+ goto pfree;
+ /* NOTREACHED */
+ case 0: /* child */
+ if (*type == 'r') {
+ if (pdes[1] != STDOUT_FILENO) {
+ dup2(pdes[1], STDOUT_FILENO);
+ close(pdes[1]);
+ }
+ if(do_stderr)
+ dup2(STDOUT_FILENO, STDERR_FILENO);
+ close(pdes[0]);
+ } else {
+ if (pdes[0] != STDIN_FILENO) {
+ dup2(pdes[0], STDIN_FILENO);
+ close(pdes[0]);
+ }
+ close(pdes[1]);
+ }
+ execv(gargv[0], gargv);
+ gargv[0] = argv[0];
+ execv(gargv[0], gargv);
+ _exit(1);
+ }
+ /* parent; assume fdopen can't fail... */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ close(pdes[0]);
+ }
+ pids[fileno(iop)] = pid;
+
+pfree:
+ for (argc = 1; gargv[argc] != NULL; argc++)
+ free(gargv[argc]);
+
+
+ return (iop);
+}
+
+int
+ftpd_pclose(FILE *iop)
+{
+ int fdes, status;
+ pid_t pid;
+ sigset_t sigset, osigset;
+
+ /*
+ * pclose returns -1 if stream is not associated with a
+ * `popened' command, or, if already `pclosed'.
+ */
+ if (pids == 0 || pids[fdes = fileno(iop)] == 0)
+ return (-1);
+ fclose(iop);
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGQUIT);
+ sigaddset(&sigset, SIGHUP);
+ sigprocmask(SIG_BLOCK, &sigset, &osigset);
+ while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
+ continue;
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
+ pids[fdes] = 0;
+ if (pid < 0)
+ return (pid);
+ if (WIFEXITED(status))
+ return (WEXITSTATUS(status));
+ return (1);
+}
OpenPOWER on IntegriCloud