diff options
Diffstat (limited to 'contrib/tnftp')
34 files changed, 24972 insertions, 0 deletions
diff --git a/contrib/tnftp/COPYING b/contrib/tnftp/COPYING new file mode 100644 index 0000000..31acb74 --- /dev/null +++ b/contrib/tnftp/COPYING @@ -0,0 +1,47 @@ +Copyright 1999, 2000 Luke Mewburn <lukem@netbsd.org>. 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 Luke Mewburn. +4. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +This product also contains software developed by other people, and you +are advised to read the various source files to read the full details +of the other licenses. Those licenses also require the following +acknowledgements: + + This product includes software developed by the NetBSD Foundation, + Inc. and its contributors. Those contributors include: + - Jaromir Dolecek + - Klaus Klein + - Luke Mewburn + - Jason R. Thorpe of the Numerical Aerospace Simulation + Facility, NASA Ames Research Center. + + This product includes software developed by the University of + California, Berkeley and its contributors. Those contributors include: + - Christos Zoulas of Cornell University. + - Guido van Rossum. + + This product includes software developed by Christos Zoulas. + diff --git a/contrib/tnftp/ChangeLog b/contrib/tnftp/ChangeLog new file mode 100644 index 0000000..8bdbb45 --- /dev/null +++ b/contrib/tnftp/ChangeLog @@ -0,0 +1,1084 @@ +Mon Jun 10 08:12:35 UTC 2002 lukem + + * crank FTP_VERSION from 1.6-beta1 to 1.6-beta2 + + * replace missing fseeko(), with a wrapper to fseek() which + checks that the offset isn't > LONG_MAX + + * #include <regex.h> #if HAVE_REGEX_H + +Mon Jun 10 01:27:46 UTC 2002 lukem + + * check for and replace sa_family_t definition + + * don't bother checking for issetugid(); it was only used in the + internal libedit to prevent $HOME/.editrc from being used if + running set-id, and the newer libedit code wouldn't even read + $HOME/.editrc if issetugid() wasn't available. as many target + operating systems don't have issetugid(), and lukemftp isn't + likely to be run set-id (and $HOME/.netrc is used in any case), + the issetugid() check has been disabled in libedit. + + * add back cpp code which #defines REGEX #if HAVE_REGEX_H + +Wed Jun 5 14:39:11 UTC 2002 lukem + + * crank FTP_VERSION from 1.6alpha1 to 1.6-beta1 + + * implement replacement setprogname() + + * use getprogname() instead of __progname + + * convert to christos' replacement fgetln(), as it's better than mine + + * merge ftp from NetBSD 20020605 to 20020606: + - use setprogname() + - only support -6 if INET6 is defined + +Wed Jun 5 13:08:25 UTC 2002 lukem + + * don't bother checking if <glob.h> is usable (see below). + + * always compile in local glob; it's the best way to ensure that + various security issues are fixed + + * update libukem/glob.c from NetBSD's __glob13.c rev 1.22 and rev 1.23 + + * merge libedit from NetBSD 20010413 to 20020606: + - constify; passes all gcc and lint strict checks. + - add config.h [Jason Evans], to create a portable version of + libedit that can be easily compiled on other OS's. + - PR/12963:Jason Waterman: Fix signed cast problems. + - Fixed an __P remnant + - Close quoting. + - Generate <>& symbolically. + - Punctuation and whitespace nits, fix a typo. + - PR/14188: Anthony Mallet: Provide an opaque data + pointer to client programs. + - a couple of minor fixes. originally by Ruslan Ermilov + <ru@FreeBSD.org>, highlighted to me by way of Mike Barcroft + <mike@FreeBSD.org> (thanks!) + - PR/14067: Anthony Mallet: Provide a programmatic way + to set the read_char function via a new el_set() operation. + Thanks, nicely done :-) + - `existent', not `existant' + - Don't use HAVE_ yet. + - Fix a warning. + - Remove an unused variable. + - If term_init() fails, cleanup and return NULL. This + avoids other lossage. Pointed by charles. + - va_{start,end} audit: Make sure that each va_start has one + and only one matching va_end, especially in error cases. + If the va_list is used multiple times, do multiple + va_starts/va_ends. If a function gets va_list as argument, + don't let it use va_end (since it's the callers + responsibility). Improved by comments from enami and + christos -- thanks! + - history_def_enter: fix off-by-one mistake in delete + condition (the behaviour to keep at least one entry on the + history list is retained). This fixes lib/9704 by Phil Nelson. + + * merge ftp from NetBSD 20020524 to 20020605: + - when showing the final progress bar, replace "00:00 ETA" + with the elapsed time. (suggested by simonb) + - actually display transfer stats after a URL fetch. + (bug introduced a *long* time ago) + - update copyright & version + + * merge ftp from NetBSD 20001127 to 20020524: + - Use "r+" instead of "r+w", since the latter is not standard. + Noted by <Steve.McClellan@radisys.com> in private email. + - Only send port number in HTTP/1.1 Host: request if port != + 80. Fixes [bin/15415] from Takahiro Kambe + <taca@sky.yamashina.kyoto.jp> + - Fix bad mode passed by mls() to recvrequest(). Fixes + [bin/16642] from <steve.mcclellan@radisys.com> + - update copyrights + - minor knf + - invoke cmdtab.c_handler()s with argv[0] == c_name instead + of the supplied name. that way the full (unambiguous) name + is displayed in error messages and usage strings. + - line2 may overrun if line is too long (> 200). be more + careful on strcpy. + - Handle URLs without files correctly (e.g, when using '-o -'). + Fix from Anders Dinsen <anders@dinsen.net> in [bin/13768] + - portnum is unsigned, use %u instead of %d + - Add -4 to force IPv4 and -6 to force IPv6 address usage. + From Hajimu UMEMOTO, via Mike Heffner of FreeBSD. + - use u_char instead of char in base64_encode(). + problem noticed by Jorgen Lundman in private mail. + - don't make broken file with -R option. + - handle "*" in Content-Range properly. + - If no_proxy condition is true && urltype == FTP_URL_T, + use fetch_ftp to retrieve + - convert to use getprogname() + - Fix description for "form", "mode", and "struct" commands. + Inspired by [bin/16736] from Steve McClellan + <steve.mcclellan@radisys.com> + - Generate <>& symbolically. I'm avoiding .../dist/... + directories for now. + - Punctuation nits. + - Whitespace cleanup. + - put "site" in alphabetical order. noted by Mike Barcroft + in private email + - avoid buffer overrun on PASV from malicious server. + - Large file ASCII mode support by using fseeko() + instead of fseek(). From Andrey A. Chernov of FreeBSD, + via Mike Heffner. + - Deal with const'ification if el_parse(). + - call setlocale() on startup + - display a limited progress bar (containing bytes xferred + and xfer rate) when the file size is unknown + - disable progress bar during remglob() + +Thu Mar 14 05:41:49 UTC 2002 lukem + + * ensure all AF_INET6 use is protected with #ifdef INET6 + + * remove unnecessary __attribute__ goop + + * libukem/snprintf.c: fix compile errors with gcc 3.x + +Tue Apr 17 08:07:29 UTC 2001 lukem + + * autoconf check for %q long long support in *printf() + (instead of %ll), define and use HAVE_PRINTF_QD if so + + * ipv6 isn't compatible with socks, so disable the former + + * look for <libutil.h> (instead of <util.h>) and <arpa/nameser.h> + + * don't check for fparseln() twice + + * fix getaddrinfo() checks + + * crank FTP_VERSION from 1.5 to 1.6alpha1 + + * always ensure _PATH_BSHELL and _PATH_TMP are defined + + * prototype inet_pton() if its missing + + * don't bother trying to use if_indextoname() in ip6_sa2str() + (fixes problems on MacOS X) + + * in inet_pton(), pull in <arpa/nameser.h> for IN6ADDRSZ and INT16SZ, + and define if missing + +Fri Apr 13 15:24:44 UTC 2001 lukem + + * only include <arpa/nameser.h> if we have it + + * update glob(3) to netbsd-current (20010329), adding support + for GLOB_LIMIT and fixing various buffer overflows. + + * update editline from NetBSD 20000915 -> NetBSD 20010413 + - Enlarge editline buffers as needed to support arbitrary + length lines. This also addresses lib/9712 by Phil Nelson. + - consistently check for allocation failures and return -1, + if we could not get more memory. + - add support for home and end keys. + - improve debugging support + - el_line_t: make 'limit' const + +Mon Nov 27 23:23:40 EST 2000 lukem + + * merge ftp from NetBSD-current (20001127): + - implement "mreget"; as per "mget" but uses "reget" instead + of "get" + - add -N netrc and $NETRC, as methods to select an alternative + .netrc file + - cache local user name and home directory for further use + - in mget(), use docase() instead of a local version to do + the case conversion. + - format string cleanups + - be more explicit that $ftp_proxy and $http_proxy are not + supported for interactive sessions + - cope with 2553bis getnameinfo (always attach scope id) + getnameinfo error check. + - use NI_MAXHOST with getnameinfo. we can assume presence of + getnameinfo. + +Tue Nov 7 00:16:23 EST 2000 lukem + + * libukem/snprintf.c had a non-functional `%s' due to a + function declaration mismatch. problem found and fixed + by Hubert Feyrer <hubert@feyrer.de> + +Wed Oct 11 14:06:19 EST 2000 lukem + + * released version 1.5 + +Tue Oct 3 10:22:36 EST 2000 lukem + + * crank to version 1.5 beta6 + + * merge ftp from NetBSD-current (20001003) + - explicitly use SOCK_STREAM with socket() instead of + res->ai_socktype, because it appears that linux with glibc + doesn't set the latter correctly after one of getaddrinfo() + or getnameinfo(). + - clarify that $ftp_proxy only works for full URLs and can't + be used for interactive connections. + +Mon Sep 25 21:52:12 EST 2000 lukem + + * crank to version 1.5 beta5 + +Sun Sep 24 13:31:19 EST 2000 lukem + + * merge ftp from NetBSD-current (20000924) + - since everything else here uses ANSI C, we might as well + replace __STRING() with the ANSI C stringization stuff... + - base64_encode should be static. picked up by hp/ux(!) + compiler + - It appears that whilst Apache 1.3.9 incorrectly puts a + trailing space after the chunksize (before the \r\n), + Apache 1.3.11 puts *multiple* trailing spaces after the + chunksize. I 'm fairly certain that this is contrary to + RFC 2068 section 3.6, but whatever... + Found by David Brownlee <abs@mono.org> + - always include <netdb.h>, not just when INET6 is defined. + resolves PR [bin/10970] by Richard Earnshaw + <rearnsha@cambridge.arm.com>> + - in progressmeter() perform the check for foregroundproc() a + little earlier + - removed unused variable `items' in list_vertical() + +Sat Sep 23 15:43:34 EST 2000 lukem + + * remove unused sverrno in warnx() and errx() + + * remove unused h_error in getnameinfo() + + * in getaddrinfo(), don't bother declaring in6_addrany[] and + in6_loopback #ifndef INET6 + +Thu Sep 21 11:26:35 EST 2000 lukem + + * in getaddrinfo.c::str_isnumber(), use strtol() and check the + result, instead of using strtoul() and not checking the result. + + * define INADDRSZ if it's not found (e.g, HP/UX doesn't seem to have + it in <arpa/nameser.h>) + +Wed Sep 20 09:23:59 EST 2000 lukem + + * crank to version 1.5 beta4 + +Mon Sep 18 18:19:54 EST 2000 lukem + + * add AC_AIX test, which defines _ALL_SOURCE under AIX + + * use ANSI # stringization instead of __STRING() + + * define HAVE_RFC2553_NETDB if <netdb.h> defines AI_NUMERICHOST + (et al) and has getaddrinfo(). (some systems only implement RFC2133) + + * don't bother with AC_C_CONST as we depend upon ANSI C elsewhere + + * when HAVE_RFC2553_NETDB isn't set, and we're #defining various EAI_, + AI_, and NI_ items, #undef first incase a system partially implements + these in <netdb.h> + + * look for tgetent() in -ltinfo before -lncurses, because ncurses 5.0 + has been split up into multiple libraries. + from Arkadiusz Miskiewicz <misiek@pld.org.pl> + +Fri Sep 15 01:09:10 EST 2000 lukem + + * don't bother defining __P() or __STRING() based on whether + __STDC__ is available or not, since these aren't used any more + + * fix mkstemp() prototype + + * declare getpass() if necessary + + * we don't need the readline xxgdb hack in libedit... + + * convert to ansi declarations + + * use ansi prototypes instead of __P() + + * merge in changes from makelist 1.4 -> 1.6: + - generate ansi prototypes instead of using __P(). noted by + christos + - fix a couple of comments + - add -m option to makelist, which generates an mdoc table + with the key bindings and their descriptions + - manually add the output of 'sh ./makelist -m vi.c ed.c + common.c' to a new section in editrc(5) called + `EDITOR COMMANDS' + + * merge libedit from NetBSD-current (20000915) + * convert to new style guide, which includes: + - ansi prototypes & features (such as stdargs) + - 8 space indents + * history_def_set has a `const int' as a third arg, not an + `int'. picked up by the ultrix compiler, reported by + simonb@ ... + * generate ansi prototypes instead of using __P(). noted by + christos. fix a couple of comments + * make xxgdb and a gdb linked with libedit's readline emulation + work properly together. xxgdb communicates with a gdb + running on a pty that it sets to -echo,-onlcr prior to + forking the gdb process. GNU readline preserves the -echo + setting while libedit was undoing it (setting the tty to a + sane state and totally confusing xxgdb's parser). + this diff simply disables libedit if both readline emulation + and "stty -echo" are used/set. that is enough to make + xxgdb work once again, but (XXX) this is not how GNU readline + handles stty -echo (it does not echo anything, but editing + commands like ^A,^K, etc. still work), so the readline + emulation isn't perfect. + +Tue Aug 29 18:00:08 EST 2000 lukem + + * don't bother testing for #if __STDC__; just assume we have it... + +Mon Aug 28 22:45:08 EST 2000 lukem + + * refine tests for IPv6 #defines (EAI_, AI_, NI_, ...). + should improve portability on systems which implement + RFC 2133 but not RFC 2553. + +Wed Aug 9 02:12:51 EST 2000 lukem + + * use #if __STDC__ instead of #ifdef __STDC__ + + * only test 'case NETDB_INTERNAL:' if it's defined + + * fix support for --program-prefix et al + + * only include <arpa/nameser.h> in the files that need it, because + the DELETE define in some system's implementations causes name + collisions in libedit. + +Mon Aug 7 08:17:37 EST 2000 lukem + + * merge ftp from NetBSD-current (20000807) + * implement parseport(), which takes a string and attempts to + convert it to a numeric port number + * use parseport() in parse_url() and hookup() + * don't try and lookup the port number using getaddrinfo(), + as it's too hard to separate a failed host name lookup from + a failed service name lookup. this was causing lossage on + systems that don't have `http' in services(5) (such as + solaris), but only crept in when we started using + getaddrinfo() unconditionally. + +Wed Aug 2 23:43:50 EST 2000 lukem + + * crank to version 1.5 beta3 + + * define NO_LONG_LONG not NO_QUAD + + * detect if struct sockaddr.sa_len exists (rather than relying upon + #ifdef BSD4_4) + + * detect if socklen_t exists, and if not, typedef as unsigned int + + * detect if struct addrinfo exists, and if not declare it and #define + associated EAI_, AI_, and NI_ defines. + + * look for & replace: getaddrinfo(), getnameinfo(), inet_ntop(), + inet_pton() + * look for gethostbyname2() + + * don't bother looking for hstrerror() or inet_aton() anymore + + * include <arpa/nameser.h> and <stddef.h> + + * define USE_SELECT instead of __USE_SELECT + + * always define HAVE_H_ERRNO + + * add Brian Stark to THANKS, for lots of AIX porting feedback + + * improve detection of sin_len for AIX (now part of sa_len test) + + * add functions needed by recent ftp import: + getaddrinfo(), getnameinfo(), inet_ntop(), inet_pton() + remove functions not needed anymore: + hstrerror(), inet_aton() + + * use #if HAVE_ISSETUGID not #ifdef + + * update from NetBSD-current (20000802): + - rename NO_QUAD to NO_LONG_LONG, QUAD* -> LL* and add ULL* + (unsigned) equivalents. name change suggested by Klaus + Klein <kjk@netbsd.org> + - change defined(BSD4_4) || HAVE_SIN_LEN tests into + HAVE_SOCKADDR_SA_LEN, and set the latter if BSD4_4 exists + +Mon Jul 31 10:59:10 EST 2000 lukem + + * merge ftp from NetBSD-current (20000731) + - we can't just rename BSD4_4 -> HAVE_SIN_LEN, since bsd + systems define BSD4_4; change tests to test for either + defined(BSD4_4) or HAVE_SIN_LEN + - more KNF + +Sun Jul 30 16:55:09 EST 2000 lukem + + * merge ftp from NetBSD-current (20000730): + - clean up NO_QUAD support: create helper #defines and use as + appropriate: + #define NOQUAD ! NOQUAD + ------- ------ - ------ + QUADF "%ld" "%lld" + QUADFP(x) "%" x "ld" "%" x "lld" + QUADT long long long + STRTOL(x,y,z) strtol(x,y,z) strtoll(x,y,z) + - always use getaddrinfo() and getnameinfo() instead of + maintaining two code paths. + - rename __USE_SELECT to USE_SELECT + - rename BSD4_4 to HAVE_SIN_LEN + - replace union sockunion {} with struct sockinet {}, and + modify the code accordingly. this is possibly more portable, + as it doesn't rely upon the structure alignment within the + union for our own stuff. + +Fri Jul 28 22:11:17 EST 2000 lukem + + * merge ftp from NetBSD-current (20000728): + - no trailing , on last item (FEAT_max) in enum + - rename "opts" to "remopts", so people used to "o host" + don't get bitten + +Wed Jul 26 18:59:19 EST 2000 lukem + + * merge ftp from NetBSD-current (20000726): + - add support for FEAT and OPTS commands with `features' and + `opts'. (from RFC 2389). + - add support for MLST & MLSD (machine parseble listings) + with 'mlst', 'mlsd' and 'pmlsd' (mlsd |$PAGER) commands. + (from draft-ietf-ftpext-mlst-11) + - rename remotesyst() to getremoteinfo(), and modify to parse + the result from FEAT (if supported), and take into account + the support for the various extensions such as MDTM, SIZE, + REST (STREAM), MLSD, and FEAT/OPTS. + - put each feature into one of the following categories: + - known to work (explicit FEAT) + - unknown but assume works until explicit failure, + when it's then tagged as `known not to work'. + - known not to work (FEAT succeeded but didn't return + anything, or was unknown and then explicit failure) + assign results into features[] matrix. + - add support to getreply() so that an optional callback will + be called for each line received from the server except for + the first and last. this is used in FEAT (and MLST) parsing. + - modify various commands to check if REST (STREAM), MDTM and + SIZE are explicitly or implicitly supported before using. + - fix `syst' when verbose is off. + - minor knf (indent goto labels by one space, etc). + - simply various command usage handlers by assuming that + argv != NULL except for quit() and disconnect(). + - errx?/warnx? audit. do not pass variable alone, use %s. + + * check for issetugid() and don't use in libedit if it doesn't exist. + + * merge libedit from NetBSD-current (20000726): + * Only look in home directory for .editrc. (Discussed + with Christos.) + + * in glob.c #undef TILDE before redefining, because some AIX systems + #define TILDE in <sys/ioctl.h> + +Mon Jul 10 00:28:51 EST 2000 lukem + + * released lukemftp 1.4 + +Thu Jun 15 23:28:49 EST 2000 lukem + + * merge ftp from NetBSD-current (20000615): + * migrate the SYST parsing from setpeer() into a separate + remotesyst(). call remotesyst() only when login has been + successful some servers don't let you run SYST until you've + successfully logged in. + * in fetch_ftp(), always call setpeer() with autologin + disabled, and use the following ftp_login() to DTRT. this + prevents ftp from trying to login a second time if the + first autologin fails when connecting to a remote site + anonymously using autofetch. + * reset unix_proxy and unix_server in cleanuppeer() + * missed a function conversion in the KNF sweep... + +Mon Jun 12 01:16:12 EST 2000 lukem + + * change lukemftp.h to check !HAVE_STRDUP instead of !HAVE_STRSUP. + fixes compile problem on systems which have strdup() as a macro. + + * merge ftp from NetBSD-current (20000612): + from itojun: better fix for previous (doesn't need + in_addr_t or u_int32_t) + +Sun Jun 11 12:19:52 EST 2000 lukem + + * merge ftp from NetBSD-current (20000611): + portability fixes for lukemftp: + * initconn(): use in_addr_t instead of u_int32_t when + manipulating IPv6 addresses (and assume anything with ipv6 + has in_addr_t; if not, i'll add an autoconf test for it) + * ai_unmapped(): not all systems have sin_len; so only set + #ifdef BSD4_4 + * fix some lint + +Mon Jun 5 21:10:31 EST 2000 lukem + + * released lukemftp 1.3 + +Mon Jun 5 19:53:49 EST 2000 lukem + + * convert various support files to ANSI C + + * look for strtoll() instead of strtoq() + + * update COPYRIGHT, THANKS, NEWS + + * merge ftp from NetBSD-current (20000605): + - fix ai_unmapped() to be a no-op in the !def INET6 case + - display `(-INET6)' at the end of the version string if + !def INET6 + - clarify in the man page that IPv6 support may not be present + (for lukemftp :) + + * ensure <vis.h> has VIS_WHITE et al + +Sun Jun 4 18:00:07 EST 2000 lukem + + * merge ftp from NetBSD-current (20000604): + - Change `ls' to use the `LIST' and not `NLST' FTP protocol + command. Now that after many years on not caring we find + certain popular ftp servers are starting to obey RFC959 to + the letter of the law and will only return a list of + filenames (not directories or other filetypes) in the + output of `NLST', then `LIST' is more useful in this case. + (Note that the aforementioned pedanticness means that + filename completion isn't as useful as it could be...) + Fixes [bin/8937] by David A. Gatwood + <dgatwood@deepspace.mklinux.org> + - convert to ANSI KNF + - Add support for `fget localfile', which reads a list of + filenames to retrieve from localfile. Based on work by + Darren Reed. + - Update copyright dates. + - s/strtoq/strtoll/ (the latter is standardised) + - Add support for 'ftp -u url file ...', to upload a list of + files to given url. Mostly based on [bin/10019] by Scott + Aaron Bamford <sab@ansic.net> + - convert IPv4 mapped address (::ffff:10.1.1.1) into real IPv4 + address before touching it. IPv4 mapped address complicates + too many things in FTP protocol handling. + - do not pass scoped IPv6 address notation on Host: directive, + since scope identifier is local to the originating node. + do not allow scoped IPv6 address notation in URL, if it is + via proxy. + - fixes from cgd: + * sanity check a length (otherwise certain bogus responses + can crash ftp) + * allow a transfer encoding type of `binary'; certain + firewall vendors return this bogus type... + - make debugging output unambiguous on IPv6 numeric addrs + (don't use host:port) + - http://[::1]:8080/ is legal. + - send Host: directive with RFC2732 bracket notation for IPv6 + numeric, otherwise "host:port" is ambiguous to servers + (clarification will be submitted as update to RFC2732). + - only use getaddrinfo() et al if both NI_NUMERICHOST *and* + INET6 are defined... (allows --disable-ipv6 in lukemftp's + configure script to disable this as well, which is good for + testing when it appears getaddrinfo() is borken) + - updated comment on IPv4 mapped address. sync with kame. + - Fix examples on using pipes in local filenames. AFAICT, + ftp has always required `dir . |more' not as `dir |more' + treats `|more' as the remote filename. Resolves [bin/9922] + by Geoff Wing <mason@primenet.com.au> + - ftp(1): treats IPv4 mapped destination as IPv4 peer, not + native IPv6 peer. this does not support network with SIIT + translator. + - inhibit too-noisy message for scoped address data transfer + (will be enabled in "debug" mode). + - only use IPTOS_ setsockopt()s if they're defined (e.g, SunOS + doesn't). from Havard.Eidnes@runit.sintef.no + - allow IPv6 extended numeric address in host part. + (draft-ietf-ipngwg-scopedaddr-format-01.txt). fixes PR 9616. + + * merge libedit from NetBSD-current (20000604): + - use strtol() (instead of atoi()) for sane error detection + +Wed May 31 19:24:53 EST 2000 lukem + + * merge libedit from NetBSD-current (20000531): + - Fix refresh glitches when using auto-margin. + - Don't dump core on empty .editrc files. + - el_insertstr takes a "const char *" not "char *" now as it + doesn't modify the argument. + +Thu Feb 3 20:19:40 EST 2000 lukem + + * released lukemftp 1.2 + +Tue Feb 1 09:47:51 EST 2000 lukem + + * add --enable-ipv6 and --disable-ipv6 to configure + + * modify libedit/sig.? to use sigfunc instead of sig_t, and + deprecate autoconf tests for retsigtype and sig_t. + This fixes portability problems with Digital UNIX 5.0. + + * merge ftp from NetBSD-current (20000201): + - define private type `sigfunc' as + typedef void (*sigfunc) __P((int)); + and replace use of sig_t and void (*)(int). + certain other OSes define sig_t differently to that (they + add extra arguments), and it causes problems due to + function mismatches, etc... + +Wed Jan 26 22:54:38 EST 2000 lukem + + * search for tgetent() in -ltermcap then -lcurses and -lncurses + + * merge ftp from NetBSD-current (20000126): + - roll back to using sscanf() instead of strptime() to parse + `yyyymmddhhmmss' strings, since the latter technically can't + parse dates without non alphanumerics between the elements + (even though NetBSD's strptime() copes). + +Tue Jan 25 19:09:37 EST 2000 lukem + + * merge ftp from NetBSD-current (20000125): + - complete_ambiguous(): be consistent about completing + unambiguous matches; if the word is already complete then + return CC_REFRESH so that the higher layer may append a + suffix if necessary. Fix from Launey Thomas <ljt@alum.mit.edu> + - change references from draft-ietf-ipngwg-url-literal-01.txt + to RFC2732 + - work around bug in apache 1.3.9 which incorrectly puts a + trailing space after the chunksize. noted by Jun-ichiro + itojun Hagino <itojun@itojun.org> in [bin/9096] + - work around lame ftpd's that don't return a correct post-Y2K + date in the output of `MDTM'. obviously the programmer of + aforementioned lame ftpd's did something like + "19%02d", tm->tm_year + instead of + "%04d", tm->tm_year + TM_YEAR_BASE + fixes [bin/9289] by jbernard@mines.edu + + * merge libedit from NetBSD-current (20000125): + - PR/9244: Kevin Schoedel: libedit dumps bindings + inconsistently + - PR/9243: Kevin Schoedel: libedit ignores repeat count + - Add support for automatic and magic margins (from tcsh) + This makes the rightmost column usable on all programs + that use editline. + +Tue Dec 21 08:59:22 EST 1999 lukem + + * update INSTALL notes for some systems + + * if sl_init() exists, check return value of sl_add() is int and + compile in a replacement copy if it's not the case + + * don't look for <stringlist.h> - always use local prototypes; older + NetBSD systems may have conflicting prototypes + +Mon Dec 20 11:21:28 EST 1999 lukem + + * merge ftp from NetBSD-current (19991220): + - Move version from ftp_var.h to version.h + - Fix chunked support; probably broke after rate limiting was added. + Problem noticed/debugging assisted by giles lean + <giles@nemeton.com.au>. + - remove unnecessary freeaddrinfo(res), since res0 was changed to be + freed earlier in itojun's last commit. fixes [bin/8948]. + - remove `const char *reason'; it was being assigned but not used. + - fix memory leak in fetch_url (no freeaddrinfo was there). + sync with recent KAME. + - separate out the main `data pump' loop into two: one that supports + rate limiting and one that doesn't. simplifies the code, and speeds + up the latter case a bit, at the expense of duplicating a few + lines... + +Sun Nov 28 18:20:41 EST 1999 lukem + + * merge ftp from NetBSD-current (19991128): + - implement xsl_init() and xsl_add(); error checking forms of + sl_{init,add}() + - fix bug where the second press of <TAB> on an empty word (i.e, list + all options) may have resulted in an strncmp() against NULL. + (detected by _DIAGASSERT()) + - in cleanuppeer(), reset username to NULL after free()ing it. + fixes [bin/8870] by Wolfgang Rupprecht <wolfgang@wsrcc.com> + - complete_remote(): use remglob("", ...) instead of remglob(".", ...), + for listings of the current working directory; some ftp servers don't + like `NLST .'. + [noted by Giles Lean <giles@nemeton.com.au>] + - recvrequest(): treat remote=="" as remote==NULL when calling + command(). (to support the above change) + - support `[user@]' in `[user@]host' and `[user@]host[:][path]'. + [based on idea (and initial code) from David Maxwell <david@fundy.ca>] + - `idle' may be invoked without any args + - reformat some comments + - reformat usage string in program and man page + - call updateremotepwd() after successful login, not after successful + connect + - always call setsockopt(, IPPROTO_IP, IP_TOS, ) (et al); using #if + defined(IPPROTO_IP) doesn't work on certain foreign systems where + enums instead of #defines are used... + [noted by Matthias Pfaller <leo@dachau.marco.de>] + +Mon Nov 15 23:01:58 EST 1999 lukem + + * released lukemftp 1.1 + +Mon Nov 15 09:07:01 EST 1999 lukem + + * merge libedit from NetBSD-current (19991115): + - instead of using a private coord_t global variable to store + the size of the rprompt, use the previously unused coord_t + el->el_rprompt.p_pos + +Sat Nov 13 14:42:22 EST 1999 lukem + + * support caching of results in AC_MSG_TRY_{COMPILE,LINK} + autoconf tests + + * add NEWS file + + * clarify copyright statement in COPYING + + * merge ftp from NetBSD-current (19991113): + - implement `set rprompt'; right side version of `set prompt'. + depends on EL_RPROMPT support i added to editline(3). + - allow $FTPPROMPT and $FTPRPROMPT to override defaults for + the relevant prompts + - move `%' formatting code from prompt() to expandbuf(). + - implement `%.' and `%c', similar to the same % codes in + tcsh(1) (functionality I added to tcsh nearly 6 years ago), + except that `%.' always does `...trailing' and `%c' always + does `/<x>trailing'. + - unknown `%foo' codes get printed as `%foo' + - implement updateremotepwd(); update the global variable + `remotepwd' to contain the remote working directory. + - add `set prompt', a user configurable prompt. (defaults to + `ftp> '). the following escape characters a la tcsh(1) are + supported: %/, %m, %M, and %n. + - add global var `username'; used by prompt code + - fix a couple of minor memory leaks + - bump version + - prevent minor memory leak (unnecessary strdup) + - implement restarting file:/// non-proxied http:// URLs + (with -R). + - fix a semicolono which stopped file:/// from working + - split the version string into product and version + - be consistent about reporting the version between: + + status command + + about:version URL fetch + + User-agent sent in http requests + - hookup(): when using getservbyname() (when getaddrinfo() + isn't available), if the provided port is a valid number + use that rather than trying to do getservbyname() against + it. fixes a problem on foreign systems noted by Chuck + Silvers <chuq@chuq.com> + - support `about:version'. also display the version in the + output of `status'. + + * merge libedit from NetBSD-current (19991113): + - implement printing a right-side prompt. code derived from + similar work I wrote for tcsh(1) three years ago. + - implement EL_RPROMPT, which allows a setting/getting of a + function which returns a string to be used as the + right-side prompt. + + * replace manually managed config.h.in with acconfig.h and use + autoheader to generate the former. + + * add missing entry for `#undef write' in acconfig.h (for SOCKS) + + * configure.in: + - use `LL' suffix on long long constant used to test + snprintf("%lld") + - test for EL_RPROMPT instead of EL_EDITMODE, since the + former is is a newer required feature + + * in makelist, set LC_ALL="C", in case the locale confuses awk. + problem noted by Peter Seebach <seebs@plethora.net> + +Wed Oct 27 07:00:00 UTC 1999 lukem + + * released 1.0 + + * removed libedit/TEST/test.c; no need to distribute it + +Mon Oct 25 21:59:54 EST 1999 lukem + + * released 1.0b7 + + * put VERSION string into lukemftp.h, and display with the `status' + command + +Mon Oct 25 11:36:59 EST 1999 lukem + + * merge ftp from NetBSD-current (19991025): + - fix up confirm() (broke `a' and `p' in last commit) + - simplify main loop (don't need `top' variable any more) + - use a struct sockaddr_in6.sin6_addr for the result from inet_pton(), + rather than u_char buf[16] + - add a few more comments + + new features: + - add `usage'; displays the usage of a command. + implemented by calling the c_handler() with argc = 0, argv = + "funcname". + - add `passive auto'; does the same as $FTPMODE=auto. + - add `set [option value]'; display all options, or set an option to + a value. + - add `unset option'; unset an option. + - add getoptionvalue() to retrieve an option's value, and replace a few + global variables with calls to this. + - implement cleanuppeer(), which resets various bits of state back to + `disconnected'. call in disconnect() and lostpeer(). + - support completing on `options'. + - improve recovery after a SIGINT may have closed the connection. + XXX: there's still a couple to fix + + other stuff: + - various consistency fixes in the man page. + - ensure that the command usage strings in the code and man page + match reality. + - mput/mget: check that the connection still exists before each xfer. + - minor cosmetic changes in confirm(). + - set code correctly in sizecmd() and modtime() + - don't need \n in err() strings. + - change lostpeer to take an argument (rather than casting + (sig_t)lostpeer in signal handlers) + - knf and whitespace police. + +Sun Oct 24 17:02:59 EST 1999 lukem + + * merge libedit from NetBSD-current (19991024): + - don't assume locales are not working - it may not be + the case + - re_refresh(): cast the character passed to re_addc() to + unsigned char, so we don't end up calling isprint() with + negative value when chars are signed and character value + is >= 128 + - Fix pointer arithmatic (caused problems on LP64, including + ftp dumping core when `edit' was turned off then on). + Problem solved by David Huggins-Daines <dhd@eradicator.org> + +Tue Oct 12 18:05:21 EST 1999 lukem + + * install man page from ${srcdir} not from . + +Tue Oct 12 17:00:41 EST 1999 lukem + + * released 1.0b6 + + * merge from NetBSD-current (19991012): + a few user interface and cosmetic tweaks: + - confirm(): move from util.c to cmds.c. display mnemonic + string in its prompt. add support for `q' (terminate + current xfer), `?' (show help list) + - in various signal handlers, output a linefeed only if + fromatty. + - if fgets(stdin) returned NULL (i.e, EOF), clearerr(stdin) + because you don't want future fgets to fail. this is not + done for the fgets() in the main command loop, since ftp + will quit at that point. + - unless ftp is invoked with -a, don't retain the anonftp + setting between hosts (`ftp somehost:' sets anonftp, but + you don't want that to `stick' if you close that connection + and open a new one). + +Mon Oct 11 23:06:38 EST 1999 lukem + + * check for working const + + * reorganise addition of -lukem to LIBS (was being added twice) + + * merge from netbsd-current: + - use sigjmp_buf instead of jmp_buf for sigsetjmp() buffer + + * libedit: don't bother generating & compiling editline.c, since + its component parts are compiled anyway. + +Sun Oct 10 12:08:39 EST 1999 lukem + + * released 1.0b5 + + * in libedit, use xsignal_restart() (from src/util.c) instead of + signal(); the isn't guaranteed to work on some foreign systems + (e.g, IRIX) if sigaction() is used in the same program. + + * merge from netbsd-current: + - use sigsetjmp()/siglongjump() instead of setjmp()/longjmp(); + the latter don't save the signal mask on some foreign systems. + - ensure signal handlers don't use stdio and do reset errno + if they don't exit with siglongjmp() + - use a common SIGINT handler for {send,recv}request() + - allow a second SIGINT during the "xfer aborted. waiting for + remote to finish abort." stage. if this occurs, just call + lostpeer() to close the connection. whilst this might be + considered brutal, it's also extremely handy if you're + impatient or there's lossage at the remote end. + + * add preformatted manual page + + * fix --enable-editline + +Wed Oct 6 10:19:00 EST 1999 lukem + + * released 1.0b4 + + * don't defining SIGINFO to SIGQUIT if the former doesn't exist; the + code now supports both as a method of getting the transfer stats + + * rototill signal handling in the actual data xfer routines, and + specifically set SIGQUIT to psummary in each one, to override + editline's handler + +Tue Oct 5 23:48:29 EST 1999 lukem + + * factor out SIGINFO setting into a handler that is always active + (but only prints out info if bytes > 0). only set the handler if + SIGINFO is defined + + * hijack SIGQUIT to be the same as SIGINFO + + * in {recv,send}request(), factor a lot of duplicated code out into + a `cleanup' section at the end + + * rework shell() a bit + + * enhancments from Marc Horowitz <marc@mit.edu> to improve + connection timeouts: + - implement xsignal_restart(), which only sets the SA_RESTART + flag if specifically requested + - xsignal() is now a wrapper to xsignal_restart(). INFO, + USR1, USR2 and WINCH are restartable, ALRM, INT, PIPE and + QUIT are not + - improve getreply()'s timeout code to take advantage of the + above + + * improve wording of how globbing works for `classic' URLs (host:path) + suggested by John Refling <johnr@imageworks.com> in relation to PRs + [bin/8519] and [bin/8520] + + * always compile in the `edit' command even if NO_EDITCOMPLETE defined + it's just a no-op in the latter case, which is more consistent to + the users + + * always compile in about: support (i.e, remove NO_ABOUT). i'm + entitled to some vanity in this program... + + * update copyrights + +Mon Oct 4 10:57:41 EST 1999 lukem + + * Invoke ar with `cr' not `cq' + + * Use AC_PROG_RANLIB to find ranlib, and use it on the libraries + + * Remove `makelist' from dependency list for libedit files; re-running + configure shouldn't result in rebuilding libedit + + * Add support for --{en,dis}able-editcomplete (defaults to enabled), + which prevents libedit support from being compiled in. + From Chris G. Demetriou <cgd@netbsd.org> + +Sun Oct 3 16:49:01 EST 1999 lukem + + * touch up the README + + * add COPYING, INSTALL, THANKS + + * whitespace consistency + + * in config.h, replace NO_QUAD with HAVE_QUAD_SUPPORT, and in + lukemftp.h define the former if the latter is non zero + + * change test against GETPGRP_VOID from #ifdef to #if + + * snprintf(): in the truncation case, ensure that the length + returned is the actual length, not the needed length + +Sat Oct 2 00:41:34 EST 1999 lukem + + * fix more lossage with $(srcdir) / $(VPATH) stuff; seems to work now + when configured in a separate directory + + * actually test the correct variable when determining whether to run + AC_FUNC_GETPGRP + +Fri Oct 1 19:32:22 EST 1999 lukem + + * released 1.0b3 + + * use AC_PROG_MAKE_SET + + * determine setting of NO_QUAD with configure not lukemftp.h + + * if have long long and have snprintf, test that snprintf + supports %lld. if it doesn't use private version + + * change strtoq from returning off_t to returning long long + + * updates from NetBSD mainline: + - only try epsv once per connection (i.e, don't bother again + if it fails) + - improve description of rate command + - fix up global vars; they're now externed in ftp_var.h + except when main.c includes it + - remove "pathnames.h" + +Fri Oct 1 10:08:43 EST 1999 lukem + + * updates from NetBSD mainline: + - fix determining of homedir + - parse_url(): fix checking of portnum + - move kame copyrights after bsd/tnfi ones + + * released 1.0b2 + + * add %lld and %qd support to snprintf() for displaying long long's + + * support VPATH and srcdir + +Thu Sep 30 17:19:35 EST 1999 lukem + + * released 1.0b1 + + * fix from NetBSD mainline: in empty() FD_ZERO the correct variable + +Wed Sep 29 23:34:33 EST 1999 lukem + + * major rework; reimport code from NetBSD-current 1999/09/29 into + separate subdirectories and build from there. organisation is now: + libedit replacement libedit + libukem replacements for missing functions + src main ftp source + +Mon Sep 27 00:43:12 EST 1999 lukem + + * released 1.0 a6 + +Sun Sep 26 17:17:05 EST 1999 lukem + + * released 1.0 a5 + +Sat Sep 25 00:58:28 EST 1999 lukem + + * released 1.0 a4 + +Fri Sep 24 17:07:07 EST 1999 lukem + + * released 1.0 a3 + +Fri Sep 24 16:18:29 EST 1999 lukem + + * released 1.0 a2 + +Tue Sep 21 11:38:49 EST 1999 lukem + + * import usr.src/bin/ftp and usr.src/lib/libedit sources from NetBSD diff --git a/contrib/tnftp/FreeBSD-patchset b/contrib/tnftp/FreeBSD-patchset new file mode 100644 index 0000000..2f9ff8a --- /dev/null +++ b/contrib/tnftp/FreeBSD-patchset @@ -0,0 +1,64 @@ +diff -ru src.orig/cmds.c src/cmds.c +--- src.orig/cmds.c Sun Jun 15 22:11:43 2003 ++++ src/cmds.c Sun Jun 15 21:46:37 2003 +@@ -131,6 +131,7 @@ + #include <string.h> + #include <time.h> + #include <unistd.h> ++#include <libutil.h> + + #include "ftp_var.h" + #include "version.h" +diff -ru src.orig/fetch.c src/fetch.c +--- src.orig/fetch.c Sun Jun 15 22:11:43 2003 ++++ src/fetch.c Sun Jun 15 21:46:53 2003 +@@ -69,6 +69,7 @@ + #include <string.h> + #include <unistd.h> + #include <time.h> ++#include <libutil.h> + + #include "ftp_var.h" + #include "version.h" +Only in src: ftp.cat1 +diff -ru src.orig/progressbar.c src/progressbar.c +--- src.orig/progressbar.c Sun Jun 15 22:11:43 2003 ++++ src/progressbar.c Sun Jun 15 21:50:48 2003 +@@ -50,6 +50,7 @@ + */ + #include <sys/types.h> + #include <sys/param.h> ++#include <sys/time.h> + + #include <err.h> + #include <errno.h> +@@ -57,10 +58,12 @@ + #include <stdio.h> + #include <stdlib.h> + #include <time.h> +-#include <tzfile.h> + #include <unistd.h> + + #include "progressbar.h" ++ ++#define SECSPERHOUR (60 * 60) ++#define SECSPERDAY ((long)60 * 60 * 24) + + #if !defined(NO_PROGRESS) + /* +diff -ru src.orig/util.c src/util.c +--- src.orig/util.c Sun Jun 15 22:11:44 2003 ++++ src/util.c Sun Jun 15 21:51:31 2003 +@@ -101,10 +101,11 @@ + #include <string.h> + #include <termios.h> + #include <time.h> +-#include <tzfile.h> + #include <unistd.h> + + #include "ftp_var.h" ++ ++#define TM_YEAR_BASE 1900 + + /* + * Connect to peer server and auto-login, if possible. diff --git a/contrib/tnftp/INSTALL b/contrib/tnftp/INSTALL new file mode 100644 index 0000000..97e82b0 --- /dev/null +++ b/contrib/tnftp/INSTALL @@ -0,0 +1,211 @@ +INSTALLATION INTRODUCTION +------------------------- + +This file describes how to compile and install lukemftp on your +system. + + ============================================ + = = + = NOTE: You will need an ANSI C compiler. = + = = + ============================================ + + +For most systems, execute the following to compile and install +lukemftp: + ./configure + make + make install + +A preformatted manual page (src/ftp.cat1) is also installed. If +you wish to install the source (src/ftp.1), ensure that your system +has up-to-date mandoc macros. groff ships with this macro suite, +but it has bugs. Try: + ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/share/tmac/ +for a more recent version. + + +CONFIGURATION OPTIONS +--------------------- + +lukemftp is configured using an `autoconf' generated `configure' +script. `configure' supports the following options: + +* The standard `autoconf configure' options, including: + --prefix=PREFIX install architecture-independent files in PREFIX + [/usr/local] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --srcdir=DIR find the sources in DIR [configure dir or ..] + BSD or GNU make may be required for this to work. + +* Specific options: + --enable-editcomplete Turn on command line editing and completion. + --disable-editcomplete Turn off command line editing and completion + [default: enabled]. + --enable-ipv6 Enable IPv6 support (if your OS supports it) + --disable-ipv6 Disable IPv6 support (even if your OS supports it.) + [default: enabled]. + --with-socks Compile with SOCKS firewall traversal support. + --with-socks5[=PATH] Compile with SOCKS5 firewall traversal support. + --with-socks4[=PATH] Compile with SOCKS4 firewall traversal support. + +The following environment variables can be set to override various +compiler related settings. + CC=compiler specify name of the C compiler (default: gcc or cc) + CFLAGS=flags specify flags to C compiler (default: -O -g or just -O) + LDFLAGS=flags specify flags to linker (default: none) + +This can be achieved with: + env CC="compiler" CFLAGS="flags" LDFLAGS="flags" ./configure + + + ============================================ + = = + = NOTE: You will need an ANSI C compiler. = + = = + ============================================ + + +PLATFORM SPECIFIC NOTES +----------------------- + +The following platforms & compilers have been tested: + +- AIX 4.1.5: +- AIX 4.2.1: +- AIX 4.3.3: + - Compiler: xlc -qlanglvl=ansi + version: xlC 3.1.4.10 -- C for AIX Compiler + version: ibmcxx.cmp 3.6.6.6 -- IBM C and C++ Compilers + + Configure with: + env CC="xlc" CFLAGS="-qlanglvl=ansi" ./configure + +- BSD/OS 4.0.1 (x86) +- BSD/OS 4.1 (x86) +- BSD/OS 4.1 (sparc) +- BSD/OS 4.2 (x86) + - Compiler: /bin/cc + version: gcc 2.7.2.1 + version: gcc version 2.95.2 19991024 + +- Digital UNIX 4.0b +- Digital UNIX 4.0d +- Digital UNIX 4.0f + - Compiler: cc -std + version: DEC C V5.2-036 on Digital UNIX V4.0 (Rev. 564) + version: DEC C V5.9-005 on Digital UNIX V4.0 (Rev. 1229) + + Configure with + env CC="cc -std" ./configure + + - Compiler: gcc + version: 2.95.1 + +- Digital UNIX 5.0 + - Compiler: cc + version: Compaq C V6.1-011 on Digital UNIX V5.0 (Rev. 910) + +- FreeBSD 3.4 (i386): +- FreeBSD 3.5 (i386): +- FreeBSD 4.1 (i386): + - Compiler: cc + version: gcc version 2.7.2.3 + version: gcc version 2.95.2 19991024 + +- HP/UX 10.20: +- HP/UX 11.00: + - Compiler: /opt/ansic/bin/cc -Ae + version: A.10.32.03 + + Configure with + env CC="cc -Ae" ./configure + + To generate code that will run on old architectures you + may need to add "+DAportable" to CC. + + +- IRIX 6.5.4 +- IRIX 6.5.8 + Compiler: /bin/cc + version: MIPSpro Compilers: Version 7.2.1 + Compiler: + version: gcc version 2.95.2 + +- HP/UX 11.00: +- HP/UX 11.00 64 bit: + - Compiler: /opt/ansic/bin/cc -Ae + version: A.11.01.00 + + Configure with + env CC="cc -Ae" ./configure + +- NetBSD 1.3.3 (i386) + Compiler: /usr/bin/cc + Compiler: /usr/bin/cc + + Ignore warnings about ``passing arg 3 of `tputs' from + incompatible pointer type''. + +- RedHat Linux 5.1 (?? i386) +- RedHat Linux 5.2 (?? i386) +- RedHat Linux 6.0 (Linux 2.2.10 i686) +- RedHat Linux 6.1 (Linux 2.2.5-15 i686) +- RedHat Linux 6.2 (Linux 2.2.16-3smp i686) + - Compiler: cc + version: egcs-1.1.2 + +- Slackware (Linux 2.0.35 i686) + - Compiler: cc + version: 2.7.2.3 + +- Solaris 2.6 (sparc) +- Solaris 7 (sparc) + - Compiler: /opt/SUNWspro/bin/cc + version: WorkShop Compilers 5.0 + + - Compiler: gcc + version: egcs-1.1.2 + +============= += OLD NOTES = +============= + +XXX: clean up to match reality +------------------------------ + +- RedHat Linux 5.0 (i386) + Compiler: cc + +- Solaris 2.5 (sparc) +- Solaris 7 (x86) + Compiler: /opt/SUNWspro/bin/cc + version: SC3.0 15 Dec 1993 + version: WorkShop Compilers 5.0 + Compiler: gcc + version: egcs-1.1.2 + version: gcc 2.8.1 + version: gcc 2.95.1 + +- Solaris 7 (sparc) 64 bit + Compiler: /opt/SUNWspro/bin/cc -xarch=v9 + version: WorkShop Compilers 5.0 + +- SunOS 4 + Compiler: gcc -lresolv + version: + +- SuSE Linux + Compiler: gcc + version: + + /usr/bin/ftp on SuSE Linux 6.4 is this ftp client. + + May need `gcc -L/usr/lib/termcap' if tgetent() et al aren't found. + +- Ultrix 4.5 + Compiler: cc + version: MIPS C Compiler 3.0 + Compiler: gcc + version: 2.7.2.2 diff --git a/contrib/tnftp/Makefile.in b/contrib/tnftp/Makefile.in new file mode 100644 index 0000000..3e4f298 --- /dev/null +++ b/contrib/tnftp/Makefile.in @@ -0,0 +1,33 @@ +# $Id: Makefile.in,v 1.6 1999/11/13 01:18:22 lukem Exp $ +# + +srcdir = @srcdir@ +VPATH = @srcdir@ +SHELL = /bin/sh + +@SET_MAKE@ + + +SUBDIRS = libedit libukem src + +all: ftp + +ftp: @LIBEDIT@ @LIBUKEM@ + ( cd src; ${MAKE} ) + +libedit.a: + ( cd libedit; ${MAKE} ) + +libukem.a: + ( cd libukem; ${MAKE} ) + +install clean: + @for i in ${SUBDIRS}; do \ + ( echo "$@ ===> $$i" ; cd $$i ; ${MAKE} $@ ); \ + done + +distclean: clean + @for i in ${SUBDIRS}; do \ + ( echo "$@ ===> $$i" ; cd $$i ; ${MAKE} $@ ); \ + done + rm -f Makefile config.cache config.log config.status config.h diff --git a/contrib/tnftp/NEWS b/contrib/tnftp/NEWS new file mode 100644 index 0000000..614dec0 --- /dev/null +++ b/contrib/tnftp/NEWS @@ -0,0 +1,84 @@ +This is a brief description of the new features and fixes added to +lukemftp-1.5 since the release of lukemftp-1.4. As always, the manual +page (src/ftp.cat1) is the place to look for complete descriptions. + +* Add new commands: + features list remote features supported by servers + mlsd machine parseable directory listing + mlst machine parseable file listing + remopts set options on remote features + + These require support in the remote server for the ftp extensions + described in RFC 2389 and draft-ietf-ftpext-mlst-11. + +* Fix support for the --program-prefix and --program-suffix configure + options. + +--- +This is a brief description of the new features and fixes added to +lukemftp-1.4 since the release of lukemftp-1.3. As always, the manual +page (src/ftp.cat1) is the place to look for complete descriptions. + +* Fix compilation problems on various non 4.4BSD derived platforms which + support IPv6, and on Linux systems which have strdup() as a macro. + +* During auto-fetch, don't attempt to autologin a second time if the first + time failed. + +--- +This is a brief description of the new features and fixes added to +lukemftp-1.3 since the release of lukemftp-1.2. As always, the manual +page (src/ftp.cat1) is the place to look for complete descriptions. + +* The `ls' command now uses the `LIST' directive instead of `NLST', + in order to be compatible with RFC959. + +* Add fget command, which reads a list of filenames to retrieve from + the given file. + +* Add support for uploading files on the command-line with `ftp -u'. + +* Various fixes to the IPv6 support. + +--- +This is a brief description of the new features and fixes added to +lukemftp-1.2 since the release of lukemftp-1.1. As always, the manual +page (src/ftp.cat1) is the place to look for complete descriptions. + +* During remote completion, only send ``NLST'' instead of ``NLST .'' + when reading the list of files from the remote server; some servers + don't like the trailing `.'. + +* Support a leading ``[user@]'' for ``[user@]host[:][path]'' auto-fetches + and ``[user@]host'' connections. + +* Always compile in support for setting the type of service on transfers. + Should speed up transfers on Linux systems. + +* Improve performance of non-rate-limited transfers. + +* Work around ftp servers that aren't Y2K compliant in returning the + modification time of a file. + +* Update the libedit library to support automatic and magic margins, + allowing ftp's rprompt to move an extra character to the right. + +--- +This is a brief description of the new features and fixes added to +lukemftp-1.1 since the release of lukemftp-1.0. As always, the manual +page (src/ftp.cat1) is the place to look for complete descriptions. + +* Implemented `set prompt' and `set rprompt', which allow you to + configure the prompt and right side prompt (respectively). + Some tcsh(1) style `%' escapes are supported, including + %. %c %/ %m %M %n + +* Implemented restarting of file:/// and non-proxied http:// URLs + (using -R) + +* Correctly parse remote ports given as numbers that don't appear in + the services(5) database. + +* Prevent a couple of minor memory leaks + +* Add missing compilation setting for SOCKS diff --git a/contrib/tnftp/README b/contrib/tnftp/README new file mode 100644 index 0000000..4b3a12c --- /dev/null +++ b/contrib/tnftp/README @@ -0,0 +1,61 @@ +WHAT IS LUKEMFTP? +----------------- + +`lukemftp' is what many users affectionately call the enhanced ftp +client in NetBSD (http://www.netbsd.org). The `lukem' comes from +the account name of the NetBSD developer who wrote most of the +enhancements: Luke Mewburn <lukem@netbsd.org>. + +This package is a `port' of the NetBSD ftp client to other systems. + +The enhancements over the standard ftp client in 4.4BSD (and +derivatives) include: + * command-line editing within ftp + * command-line fetching of URLS, including support for: + - http proxies (c.f: $http_proxy, $ftp_proxy) + - authentication + * configurable prompt + * context sensitive command and filename completion + * dynamic progress bar + * feature negotiation extensions from RFC 2389 + (c.f: `feat' and `remopts') + * extensions to ftp from the IETF ftpext working group + (c.f: `mlsd' and `mlst') + * IPv6 support (from the WIDE project) + * modification time preservation + * paging of local and remote files, and of directory listings + (c.f: `lpage', `page', `pdir') + * passive mode support, with fallback to active mode + * retrieval of filenames listed in a given file (c.f: `fget') + * `set option' override of ftp environment variables + * socks4/socks5 support + * TIS Firewall Toolkit gate ftp proxy support (c.f: `gate') + * transfer-rate throttling (c.f: `-T', `rate') + * uploading of files on the command line (c.f: `-u') + + +INSTALLATION +------------ + +Refer to `INSTALL' for more information on how to compile and install +lukemftp. + + +FEEDBACK / BUG REPORTS +---------------------- + +Please email feedback back to the maintainer: <lukem@netbsd.org>. + + +COPYRIGHT +--------- + +lukemftp is covered by a BSD-style copyright notice. Please refer to +the file `COPYING' for more information. + + +AVAILABILITY +------------ + +The primary ftp site for lukemftp is: + ftp://ftp.netbsd.org/pub/NetBSD/misc/lukemftp/ diff --git a/contrib/tnftp/THANKS b/contrib/tnftp/THANKS new file mode 100644 index 0000000..bff4e25 --- /dev/null +++ b/contrib/tnftp/THANKS @@ -0,0 +1,30 @@ +Whilst a lot of the work in lukemftp (both the original sources in NetBSD +and this port) was done by me (Luke Mewburn), it would not be as useable +without the enhancements, fixes, or input from the following people: + +Brian Stark <bstark1990@netscape.net> +Chris G. Demetriou <cgd@netbsd.org> +Christos Zoulas <christos@netbsd.org> +Dan Winship <danw@mit.edu> +Darren Reed <darrenr@pobox.com> +David Carrel <carrel@netbsd.org> +Giles Lean <giles@nemeton.com.au> +Havard Eidnes <Havard.Eidnes@runit.sintef.no> +ITOH Yasufumi <itohy@netbsd.org> +Jason R. Thorpe <thorpej@netbsd.org> +John Hawkinson <jhawk@mit.edu> +Joseph S. Myers <jsm28@cam.ac.uk> +Jun-ichiro itojun Hagino <itojun@netbsd.org> +Kimmo Suominen <kim@tac.nyc.ny.us> +Klaus Klein <kleink@netbsd.org> +Luke Mewburn <lukem@netbsd.org> +Marc Horowitz <marc@mit.edu> +Matthew R. Green <mrg@eterna.com.au> +Matthias Pfaller <leo@dachau.marco.de> +Matthias Scheler <tron@zhadum.de> +Michael L. Hitch <osymh@terra.oscs.montana.edu> +Scott Aaron Bamford <sab@ansic.net> +Simon Burge <simonb@thistledown.com.au> +Todd C. Miller <Todd.Miller@courtesan.com> + +Apologies to anyone I've missed. diff --git a/contrib/tnftp/acconfig.h b/contrib/tnftp/acconfig.h new file mode 100644 index 0000000..fb3cbfa --- /dev/null +++ b/contrib/tnftp/acconfig.h @@ -0,0 +1,92 @@ +/* $Id: acconfig.h,v 1.9 2002/06/10 01:27:13 lukem Exp $ */ + +@TOP@ +@BOTTOM@ + +/* Define if your compiler supports `long long' */ +#undef HAVE_LONG_LONG + +/* Define if *printf() uses %qd to print `long long' (otherwise uses %lld) */ +#undef HAVE_PRINTF_QD + +/* Define if in_port_t exists */ +#undef HAVE_IN_PORT_T + +/* Define if sa_family_t exists in <sys/socket.h> */ +#undef HAVE_SA_FAMILY_T + +/* Define if struct sockaddr.sa_len exists (implies sockaddr_in.sin_len, etc) */ +#undef HAVE_SOCKADDR_SA_LEN + +/* Define if socklen_t exists */ +#undef HAVE_SOCKLEN_T + +/* Define if AF_INET6 exists in <sys/socket.h> */ +#undef HAVE_AF_INET6 + +/* Define if `struct sockaddr_in6' exists in <netinet/in.h> */ +#undef HAVE_SOCKADDR_IN6 + +/* Define if `struct addrinfo' exists in <netdb.h> */ +#undef HAVE_ADDRINFO + +/* + * Define if <netdb.h> contains AI_NUMERICHOST et al. + * Systems which only implement RFC2133 will need this. + */ +#undef HAVE_RFC2553_NETDB + +/* Define if `struct direct' has a d_namlen element */ +#undef HAVE_D_NAMLEN + +/* Define if h_errno exists in <netdb.h> */ +#undef HAVE_H_ERRNO_D + +/* Define if fclose() is declared in <stdio.h> */ +#undef HAVE_FCLOSE_D + +/* Define if getpass() is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_GETPASS_D + +/* Define if optarg is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_OPTARG_D + +/* Define if optind is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_OPTIND_D + +/* Define if pclose() is declared in <stdio.h> */ +#undef HAVE_PCLOSE_D + +/* Define if `long long' is supported and sizeof(off_t) >= 8 */ +#undef HAVE_QUAD_SUPPORT + +/* Define if strptime() is declared in <time.h> */ +#undef HAVE_STRPTIME_D + +/* + * Define this if compiling with SOCKS (the firewall traversal library). + * Also, you must define connect, getsockname, bind, accept, listen, and + * select to their R-versions. + */ +#undef SOCKS +#undef SOCKS4 +#undef SOCKS5 +#undef connect +#undef getsockname +#undef bind +#undef accept +#undef listen +#undef select +#undef dup +#undef dup2 +#undef fclose +#undef gethostbyname +#undef getpeername +#undef read +#undef recv +#undef recvfrom +#undef rresvport +#undef send +#undef sendto +#undef shutdown +#undef write diff --git a/contrib/tnftp/aclocal.m4 b/contrib/tnftp/aclocal.m4 new file mode 100644 index 0000000..3e27508 --- /dev/null +++ b/contrib/tnftp/aclocal.m4 @@ -0,0 +1,257 @@ +dnl $Id: aclocal.m4,v 1.5 1999/11/13 10:50:39 lukem Exp $ +dnl + +dnl +dnl AC_MSG_TRY_COMPILE +dnl +dnl Written by Luke Mewburn <lukem@netbsd.org> +dnl +dnl Usage: +dnl AC_MSG_TRY_COMPILE(Message, CacheVar, Includes, Code, +dnl ActionPass [,ActionFail] ) +dnl +dnl effectively does: +dnl AC_CACHE_CHECK(Message, CacheVar, +dnl AC_TRY_COMPILE(Includes, Code, CacheVar = yes, CacheVar = no) +dnl if CacheVar == yes +dnl AC_MESSAGE_RESULT(yes) +dnl ActionPass +dnl else +dnl AC_MESSAGE_RESULT(no) +dnl ActionFail +dnl ) +dnl +AC_DEFUN(AC_MSG_TRY_COMPILE, [ + AC_CACHE_CHECK($1, $2, [ + AC_TRY_COMPILE([ $3 ], [ $4; ], [ $2=yes ], [ $2=no ]) + ]) + if test "x[$]$2" = "xyes"; then + $5 + else + $6 + : + fi +]) + +dnl +dnl AC_MSG_TRY_LINK +dnl +dnl Usage: +dnl AC_MSG_TRY_LINK(Message, CacheVar, Includes, Code, +dnl ActionPass [,ActionFail] ) +dnl +dnl as AC_MSG_TRY_COMPILE, but uses AC_TRY_LINK instead of AC_TRY_COMPILE +dnl +AC_DEFUN(AC_MSG_TRY_LINK, [ + AC_CACHE_CHECK($1, $2, [ + AC_TRY_LINK([ $3 ], [ $4; ], [ $2=yes ], [ $2=no ]) + ]) + if test "x[$]$2" = "xyes"; then + $5 + else + $6 + : + fi +]) + + +dnl +dnl AC_LIBRARY_NET: #Id: net.m4,v 1.5 1997/11/09 21:36:54 jhawk Exp # +dnl +dnl Written by John Hawkinson <jhawk@mit.edu>. This code is in the Public +dnl Domain. +dnl +dnl This test is for network applications that need socket() and +dnl gethostbyname() -ish functions. Under Solaris, those applications need to +dnl link with "-lsocket -lnsl". Under IRIX, they should *not* link with +dnl "-lsocket" because libsocket.a breaks a number of things (for instance: +dnl gethostbyname() under IRIX 5.2, and snoop sockets under most versions of +dnl IRIX). +dnl +dnl Unfortunately, many application developers are not aware of this, and +dnl mistakenly write tests that cause -lsocket to be used under IRIX. It is +dnl also easy to write tests that cause -lnsl to be used under operating +dnl systems where neither are necessary (or useful), such as SunOS 4.1.4, which +dnl uses -lnsl for TLI. +dnl +dnl This test exists so that every application developer does not test this in +dnl a different, and subtly broken fashion. +dnl +dnl It has been argued that this test should be broken up into two seperate +dnl tests, one for the resolver libraries, and one for the libraries necessary +dnl for using Sockets API. Unfortunately, the two are carefully intertwined and +dnl allowing the autoconf user to use them independantly potentially results in +dnl unfortunate ordering dependancies -- as such, such component macros would +dnl have to carefully use indirection and be aware if the other components were +dnl executed. Since other autoconf macros do not go to this trouble, and almost +dnl no applications use sockets without the resolver, this complexity has not +dnl been implemented. +dnl +dnl The check for libresolv is in case you are attempting to link statically +dnl and happen to have a libresolv.a lying around (and no libnsl.a). +dnl +AC_DEFUN(AC_LIBRARY_NET, [ + # Most operating systems have gethostbyname() in the default searched + # libraries (i.e. libc): + AC_CHECK_FUNC(gethostbyname, , + # Some OSes (eg. Solaris) place it in libnsl: + AC_CHECK_LIB(nsl, gethostbyname, , + # Some strange OSes (SINIX) have it in libsocket: + AC_CHECK_LIB(socket, gethostbyname, , + # Unfortunately libsocket sometimes depends on libnsl. + # AC_CHECK_LIB's API is essentially broken so the following + # ugliness is necessary: + AC_CHECK_LIB(socket, gethostbyname, + LIBS="-lsocket -lnsl $LIBS", + AC_CHECK_LIB(resolv, gethostbyname), + -lnsl) + ) + ) + ) + AC_CHECK_FUNC(socket, , AC_CHECK_LIB(socket, socket, , + AC_CHECK_LIB(socket, socket, LIBS="-lsocket -lnsl $LIBS", , -lnsl))) + ]) + + +dnl Checks for SOCKS firewall support. +dnl +dnl Written by Matthew R. Green <mrg@eterna.com.au> +dnl +AC_DEFUN(AC_LIBRARY_SOCKS, [ + AC_MSG_CHECKING(whether to support SOCKS) + AC_ARG_WITH(socks, + [ --with-socks Compile with SOCKS firewall traversal support.], + [ + case "$withval" in + no) + AC_MSG_RESULT(no) + ;; + yes) + AC_MSG_RESULT(yes) + AC_CHECK_LIB(socks5, SOCKSconnect, [ + socks=5 + LIBS="-lsocks5 $LIBS"], [ + AC_CHECK_LIB(socks, Rconnect, [ + socks=4 + LIBS="-lsocks $LIBS"], [ + AC_MSG_ERROR(Could not find socks library. You must first install socks.) ] ) ] ) + ;; + esac + ], + AC_MSG_RESULT(no) + ) + + if test "x$socks" = "x"; then + AC_MSG_CHECKING(whether to support SOCKS5) + AC_ARG_WITH(socks5, + [ --with-socks5[=PATH] Compile with SOCKS5 firewall traversal support.], + [ + case "$withval" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + socks=5 + if test "x$withval" = "xyes"; then + withval="-lsocks5" + else + if test -d "$withval"; then + if test -d "$withval/include"; then + CFLAGS="$CFLAGS -I$withval/include" + else + CFLAGS="$CFLAGS -I$withval" + fi + if test -d "$withval/lib"; then + withval="-L$withval/lib -lsocks5" + else + withval="-L$withval -lsocks5" + fi + fi + fi + LIBS="$withval $LIBS" + # If Socks was compiled with Kerberos support, we will need + # to link against kerberos libraries. Temporarily append + # to LIBS. This is harmless if there is no kerberos support. + TMPLIBS="$LIBS" + LIBS="$LIBS $KERBEROS_LIBS" + AC_TRY_LINK([], + [ SOCKSconnect(); ], + [], + [ AC_MSG_ERROR(Could not find the $withval library. You must first install socks5.) ]) + LIBS="$TMPLIBS" + ;; + esac + ], + AC_MSG_RESULT(no) + ) + fi + + if test "x$socks" = "x"; then + AC_MSG_CHECKING(whether to support SOCKS4) + AC_ARG_WITH(socks4, + [ --with-socks4[=PATH] Compile with SOCKS4 firewall traversal support.], + [ + case "$withval" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + socks=4 + if test "x$withval" = "xyes"; then + withval="-lsocks" + else + if test -d "$withval"; then + withval="-L$withval -lsocks" + fi + fi + LIBS="$withval $LIBS" + AC_TRY_LINK([], + [ Rconnect(); ], + [], + [ AC_MSG_ERROR(Could not find the $withval library. You must first install socks.) ]) + ;; + esac + ], + AC_MSG_RESULT(no) + ) + fi + + if test "x$socks" = "x4"; then + AC_DEFINE(SOCKS) + AC_DEFINE(SOCKS4) + AC_DEFINE(connect, Rconnect) + AC_DEFINE(getsockname, Rgetsockname) + AC_DEFINE(bind, Rbind) + AC_DEFINE(accept, Raccept) + AC_DEFINE(listen, Rlisten) + AC_DEFINE(select, Rselect) + fi + + if test "x$socks" = "x5"; then + AC_DEFINE(SOCKS) + AC_DEFINE(SOCKS5) + AC_DEFINE(connect,SOCKSconnect) + AC_DEFINE(getsockname,SOCKSgetsockname) + AC_DEFINE(getpeername,SOCKSgetpeername) + AC_DEFINE(bind,SOCKSbind) + AC_DEFINE(accept,SOCKSaccept) + AC_DEFINE(listen,SOCKSlisten) + AC_DEFINE(select,SOCKSselect) + AC_DEFINE(recvfrom,SOCKSrecvfrom) + AC_DEFINE(sendto,SOCKSsendto) + AC_DEFINE(recv,SOCKSrecv) + AC_DEFINE(send,SOCKSsend) + AC_DEFINE(read,SOCKSread) + AC_DEFINE(write,SOCKSwrite) + AC_DEFINE(rresvport,SOCKSrresvport) + AC_DEFINE(shutdown,SOCKSshutdown) + AC_DEFINE(listen,SOCKSlisten) + AC_DEFINE(close,SOCKSclose) + AC_DEFINE(dup,SOCKSdup) + AC_DEFINE(dup2,SOCKSdup2) + AC_DEFINE(fclose,SOCKSfclose) + AC_DEFINE(gethostbyname,SOCKSgethostbyname) + fi +]) diff --git a/contrib/tnftp/config.h.in b/contrib/tnftp/config.h.in new file mode 100644 index 0000000..d754334 --- /dev/null +++ b/contrib/tnftp/config.h.in @@ -0,0 +1,275 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ +/* $Id: config.h.in,v 1.28 2002/06/10 08:10:33 lukem Exp $ */ + + +/* Define if on AIX 3. + System headers sometimes define this. + We just want to avoid a redefinition error message. */ +#ifndef _ALL_SOURCE +#undef _ALL_SOURCE +#endif + +/* Define if the closedir function returns void instead of int. */ +#undef CLOSEDIR_VOID + +/* Define if the `getpgrp' function takes no argument. */ +#undef GETPGRP_VOID + +/* Define if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define if your Fortran 77 compiler doesn't accept -c and -o together. */ +#undef F77_NO_MINUS_C_MINUS_O + +/* Define to `long' if <sys/types.h> doesn't define. */ +#undef off_t + +/* Define to the type of arg1 for select(). */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for select(). */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg5 for select(). */ +#undef SELECT_TYPE_ARG5 + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Define if the closedir function returns void instead of int. */ +#undef VOID_CLOSEDIR + +/* The number of bytes in a off_t. */ +#undef SIZEOF_OFF_T + +/* Define if you have the err function. */ +#undef HAVE_ERR + +/* Define if you have the fgetln function. */ +#undef HAVE_FGETLN + +/* Define if you have the fparseln function. */ +#undef HAVE_FPARSELN + +/* Define if you have the fseeko function. */ +#undef HAVE_FSEEKO + +/* Define if you have the getaddrinfo function. */ +#undef HAVE_GETADDRINFO + +/* Define if you have the gethostbyname2 function. */ +#undef HAVE_GETHOSTBYNAME2 + +/* Define if you have the getnameinfo function. */ +#undef HAVE_GETNAMEINFO + +/* Define if you have the getpassphrase function. */ +#undef HAVE_GETPASSPHRASE + +/* Define if you have the getpgrp function. */ +#undef HAVE_GETPGRP + +/* Define if you have the inet_ntop function. */ +#undef HAVE_INET_NTOP + +/* Define if you have the inet_pton function. */ +#undef HAVE_INET_PTON + +/* Define if you have the memmove function. */ +#undef HAVE_MEMMOVE + +/* Define if you have the mkstemp function. */ +#undef HAVE_MKSTEMP + +/* Define if you have the poll function. */ +#undef HAVE_POLL + +/* Define if you have the select function. */ +#undef HAVE_SELECT + +/* Define if you have the setprogname function. */ +#undef HAVE_SETPROGNAME + +/* Define if you have the sl_init function. */ +#undef HAVE_SL_INIT + +/* Define if you have the snprintf function. */ +#undef HAVE_SNPRINTF + +/* Define if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the strlcat function. */ +#undef HAVE_STRLCAT + +/* Define if you have the strlcpy function. */ +#undef HAVE_STRLCPY + +/* Define if you have the strptime function. */ +#undef HAVE_STRPTIME + +/* Define if you have the strsep function. */ +#undef HAVE_STRSEP + +/* Define if you have the strtoll function. */ +#undef HAVE_STRTOLL + +/* Define if you have the strunvis function. */ +#undef HAVE_STRUNVIS + +/* Define if you have the strvis function. */ +#undef HAVE_STRVIS + +/* Define if you have the timegm function. */ +#undef HAVE_TIMEGM + +/* Define if you have the usleep function. */ +#undef HAVE_USLEEP + +/* Define if you have the <arpa/nameser.h> header file. */ +#undef HAVE_ARPA_NAMESER_H + +/* Define if you have the <dirent.h> header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the <err.h> header file. */ +#undef HAVE_ERR_H + +/* Define if you have the <libutil.h> header file. */ +#undef HAVE_LIBUTIL_H + +/* Define if you have the <ndir.h> header file. */ +#undef HAVE_NDIR_H + +/* Define if you have the <paths.h> header file. */ +#undef HAVE_PATHS_H + +/* Define if you have the <poll.h> header file. */ +#undef HAVE_POLL_H + +/* Define if you have the <regex.h> header file. */ +#undef HAVE_REGEX_H + +/* Define if you have the <sys/dir.h> header file. */ +#undef HAVE_SYS_DIR_H + +/* Define if you have the <sys/ndir.h> header file. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the <sys/poll.h> header file. */ +#undef HAVE_SYS_POLL_H + +/* Define if you have the <termcap.h> header file. */ +#undef HAVE_TERMCAP_H + +/* Define if you have the <util.h> header file. */ +#undef HAVE_UTIL_H + +/* Define if you have the <vis.h> header file. */ +#undef HAVE_VIS_H + +/* Define if you have the nsl library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the socket library (-lsocket). */ +#undef HAVE_LIBSOCKET + +/* Define if you have the tinfo library (-ltinfo). */ +#undef HAVE_LIBTINFO + +/* Define if you have the util library (-lutil). */ +#undef HAVE_LIBUTIL + +/* Define if your compiler supports `long long' */ +#undef HAVE_LONG_LONG + +/* Define if *printf() uses %qd to print `long long' (otherwise uses %lld) */ +#undef HAVE_PRINTF_QD + +/* Define if in_port_t exists */ +#undef HAVE_IN_PORT_T + +/* Define if sa_family_t exists in <sys/socket.h> */ +#undef HAVE_SA_FAMILY_T + +/* Define if struct sockaddr.sa_len exists (implies sockaddr_in.sin_len, etc) */ +#undef HAVE_SOCKADDR_SA_LEN + +/* Define if socklen_t exists */ +#undef HAVE_SOCKLEN_T + +/* Define if AF_INET6 exists in <sys/socket.h> */ +#undef HAVE_AF_INET6 + +/* Define if `struct sockaddr_in6' exists in <netinet/in.h> */ +#undef HAVE_SOCKADDR_IN6 + +/* Define if `struct addrinfo' exists in <netdb.h> */ +#undef HAVE_ADDRINFO + +/* + * Define if <netdb.h> contains AI_NUMERICHOST et al. + * Systems which only implement RFC2133 will need this. + */ +#undef HAVE_RFC2553_NETDB + +/* Define if `struct direct' has a d_namlen element */ +#undef HAVE_D_NAMLEN + +/* Define if h_errno exists in <netdb.h> */ +#undef HAVE_H_ERRNO_D + +/* Define if fclose() is declared in <stdio.h> */ +#undef HAVE_FCLOSE_D + +/* Define if getpass() is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_GETPASS_D + +/* Define if optarg is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_OPTARG_D + +/* Define if optind is declared in <stdlib.h> or <unistd.h> */ +#undef HAVE_OPTIND_D + +/* Define if pclose() is declared in <stdio.h> */ +#undef HAVE_PCLOSE_D + +/* Define if `long long' is supported and sizeof(off_t) >= 8 */ +#undef HAVE_QUAD_SUPPORT + +/* Define if strptime() is declared in <time.h> */ +#undef HAVE_STRPTIME_D + +/* + * Define this if compiling with SOCKS (the firewall traversal library). + * Also, you must define connect, getsockname, bind, accept, listen, and + * select to their R-versions. + */ +#undef SOCKS +#undef SOCKS4 +#undef SOCKS5 +#undef connect +#undef getsockname +#undef bind +#undef accept +#undef listen +#undef select +#undef dup +#undef dup2 +#undef fclose +#undef gethostbyname +#undef getpeername +#undef read +#undef recv +#undef recvfrom +#undef rresvport +#undef send +#undef sendto +#undef shutdown +#undef write diff --git a/contrib/tnftp/configure b/contrib/tnftp/configure new file mode 100755 index 0000000..f759085 --- /dev/null +++ b/contrib/tnftp/configure @@ -0,0 +1,4229 @@ +#! /bin/sh + +# From configure.in Revision: 1.37 + + + + + + + + + + +# Guess values for system-dependent variables and create Makefiles. +# Generated automatically using autoconf version 2.13 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. + +# Defaults: +ac_help= +ac_default_prefix=/usr/local +# Any additions from configure.in: +ac_help="$ac_help +\ + --enable-editcomplete Turn on command line editing and completion. + --disable-editcomplete Turn off command line editing and completion + [default: enabled]." +ac_help="$ac_help +\ + --enable-ipv6 Enable IPv6 support (if your OS supports it). + --disable-ipv6 Disable IPv6 support (even if your OS supports it) + [default: enabled]." +ac_help="$ac_help + --with-socks Compile with SOCKS firewall traversal support." +ac_help="$ac_help + --with-socks5[=PATH] Compile with SOCKS5 firewall traversal support." +ac_help="$ac_help + --with-socks4[=PATH] Compile with SOCKS4 firewall traversal support." + +# Initialize some variables set by options. +# The variables have the same names as the options, with +# dashes changed to underlines. +build=NONE +cache_file=./config.cache +exec_prefix=NONE +host=NONE +no_create= +nonopt=NONE +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +target=NONE +verbose= +x_includes=NONE +x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +# Initialize some other variables. +subdirs= +MFLAGS= MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 + +ac_prev= +for ac_option +do + + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + case "$ac_option" in + -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) ac_optarg= ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case "$ac_option" in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build="$ac_optarg" ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -disable-* | --disable-*) + ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + eval "enable_${ac_feature}=no" ;; + + -enable-* | --enable-*) + ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } + fi + ac_feature=`echo $ac_feature| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "enable_${ac_feature}='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he) + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat << EOF +Usage: configure [options] [host] +Options: [defaults in brackets after descriptions] +Configuration: + --cache-file=FILE cache test results in FILE + --help print this message + --no-create do not create output files + --quiet, --silent do not print \`checking...' messages + --version print the version of autoconf that created configure +Directory and file names: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] + --srcdir=DIR find the sources in DIR [configure dir or ..] + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF +Host type: + --build=BUILD configure for building on BUILD [BUILD=HOST] + --host=HOST configure for HOST [guessed] + --target=TARGET configure for TARGET [TARGET=HOST] +Features and packages: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --x-includes=DIR X include files are in DIR + --x-libraries=DIR X library files are in DIR +EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi + exit 0 ;; + + -host | --host | --hos | --ho) + ac_prev=host ;; + -host=* | --host=* | --hos=* | --ho=*) + host="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix="$ac_optarg" ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix="$ac_optarg" ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name="$ac_optarg" ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site="$ac_optarg" ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target="$ac_optarg" ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers) + echo "configure generated by autoconf version 2.13" + exit 0 ;; + + -with-* | --with-*) + ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + case "$ac_option" in + *=*) ;; + *) ac_optarg=yes ;; + esac + eval "with_${ac_package}='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`echo $ac_option|sed -e 's/-*without-//'` + # Reject names that are not valid shell variable names. + if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then + { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } + fi + ac_package=`echo $ac_package| sed 's/-/_/g'` + eval "with_${ac_package}=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes="$ac_optarg" ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries="$ac_optarg" ;; + + -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } + ;; + + *) + if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then + echo "configure: warning: $ac_option: invalid host type" 1>&2 + fi + if test "x$nonopt" != xNONE; then + { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } + fi + nonopt="$ac_option" + ;; + + esac +done + +if test -n "$ac_prev"; then + { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } +fi + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 6 checking for... messages and results +# 5 compiler messages saved in config.log +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>./config.log + +echo "\ +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. +" 1>&5 + +# Strip out --no-create and --no-recursion so they do not pile up. +# Also quote any args containing shell metacharacters. +ac_configure_args= +for ac_arg +do + case "$ac_arg" in + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c) ;; + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ac_configure_args="$ac_configure_args '$ac_arg'" ;; + *) ac_configure_args="$ac_configure_args $ac_arg" ;; + esac +done + +# NLS nuisances. +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo > confdefs.h + +# A filename unique to this package, relative to the directory that +# configure is in, which we can look for to find out if srcdir is correct. +ac_unique_file=lukemftp.h + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_prog=$0 + ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` + test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } + else + { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } + fi +fi +srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` + +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + echo "loading site script $ac_site_file" + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + echo "loading cache $cache_file" + . $cache_file +else + echo "creating cache $cache_file" + > $cache_file +fi + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +ac_exeext= +ac_objext=o +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + + + +if test "$program_transform_name" = s,x,x,; then + program_transform_name= +else + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED + program_transform_name="`echo $program_transform_name|sed -f conftestsed`" + rm -f conftestsed +fi +test "$program_prefix" != NONE && + program_transform_name="s,^,${program_prefix},; $program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$\$,${program_suffix},; $program_transform_name" + +# sed with no file args requires a program. +test "$program_transform_name" = "" && program_transform_name="s,x,x," + +# Check whether --enable-editcomplete or --disable-editcomplete was given. +if test "${enable_editcomplete+set}" = set; then + enableval="$enable_editcomplete" + opt_editcomplete=$enableval +else + opt_editcomplete=yes +fi + +# Check whether --enable-ipv6 or --disable-ipv6 was given. +if test "${enable_ipv6+set}" = set; then + enableval="$enable_ipv6" + opt_ipv6=$enableval +else + opt_ipv6=yes +fi + + +echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 +echo "configure:590: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftestmake <<\EOF +all: + @echo 'ac_maketemp="${MAKE}"' +EOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftestmake +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$ac_t""yes" 1>&6 + SET_MAKE= +else + echo "$ac_t""no" 1>&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + +# Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:619: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="gcc" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:649: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_prog_rejected=no + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + if test -z "$CC"; then + case "`uname -s`" in + *win32* | *WIN32*) + # Extract the first word of "cl", so it can be a program name with args. +set dummy cl; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:700: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_CC="cl" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + ;; + esac + fi + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:732: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext << EOF + +#line 743 "configure" +#include "confdefs.h" + +main(){return(0);} +EOF +if { (eval echo configure:748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:774: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross + +echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:779: checking whether we are using GNU C" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:788: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + ac_cv_prog_gcc=yes +else + ac_cv_prog_gcc=no +fi +fi + +echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + +if test $ac_cv_prog_gcc = yes; then + GCC=yes +else + GCC= +fi + +ac_test_CFLAGS="${CFLAGS+set}" +ac_save_CFLAGS="$CFLAGS" +CFLAGS= +echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:807: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then + ac_cv_prog_cc_g=yes +else + ac_cv_prog_cc_g=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi + +for ac_prog in mawk gawk nawk awk +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:843: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AWK="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AWK="$ac_cv_prog_AWK" +if test -n "$AWK"; then + echo "$ac_t""$AWK" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AWK" && break +done + +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:903: checking for a BSD compatible install" >&5 +if test -z "$INSTALL"; then +if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":" + for ac_dir in $PATH; do + # Account for people who put trailing slashes in PATH elements. + case "$ac_dir/" in + /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + if test -f $ac_dir/$ac_prog; then + if test $ac_prog = install && + grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + else + ac_cv_path_install="$ac_dir/$ac_prog -c" + break 2 + fi + fi + done + ;; + esac + done + IFS="$ac_save_IFS" + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL="$ac_cv_path_install" + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL="$ac_install_sh" + fi +fi +echo "$ac_t""$INSTALL" 1>&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +# Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:958: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_RANLIB="ranlib" + break + fi + done + IFS="$ac_save_ifs" + test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":" +fi +fi +RANLIB="$ac_cv_prog_RANLIB" +if test -n "$RANLIB"; then + echo "$ac_t""$RANLIB" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +for ac_prog in ar +do +# Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:990: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" + ac_dummy="$PATH" + for ac_dir in $ac_dummy; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + ac_cv_prog_AR="$ac_prog" + break + fi + done + IFS="$ac_save_ifs" +fi +fi +AR="$ac_cv_prog_AR" +if test -n "$AR"; then + echo "$ac_t""$AR" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + +test -n "$AR" && break +done + +echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:1020: checking how to run the C preprocessor" >&5 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then +if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + # This must be in double quotes, not single quotes, because CPP may get + # substituted into the Makefile and "${CC-cc}" will confuse make. + CPP="${CC-cc} -E" + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. + cat > conftest.$ac_ext <<EOF +#line 1035 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1041: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -E -traditional-cpp" + cat > conftest.$ac_ext <<EOF +#line 1052 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP="${CC-cc} -nologo -E" + cat > conftest.$ac_ext <<EOF +#line 1069 "configure" +#include "confdefs.h" +#include <assert.h> +Syntax Error +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:1075: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + : +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + CPP=/lib/cpp +fi +rm -f conftest* +fi +rm -f conftest* +fi +rm -f conftest* + ac_cv_prog_CPP="$CPP" +fi + CPP="$ac_cv_prog_CPP" +else + ac_cv_prog_CPP="$CPP" +fi +echo "$ac_t""$CPP" 1>&6 + +echo $ac_n "checking for AIX""... $ac_c" 1>&6 +echo "configure:1100: checking for AIX" >&5 +cat > conftest.$ac_ext <<EOF +#line 1102 "configure" +#include "confdefs.h" +#ifdef _AIX + yes +#endif + +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF +#define _ALL_SOURCE 1 +EOF + +else + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + + + + +echo $ac_n "checking for fparseln in -lutil""... $ac_c" 1>&6 +echo "configure:1126: checking for fparseln in -lutil" >&5 +ac_lib_var=`echo util'_'fparseln | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lutil $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1134 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char fparseln(); + +int main() { +fparseln() +; return 0; } +EOF +if { (eval echo configure:1145: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo util | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lutil $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +if test $opt_editcomplete = yes; then + echo $ac_n "checking for tgetent in -ltinfo""... $ac_c" 1>&6 +echo "configure:1174: checking for tgetent in -ltinfo" >&5 +ac_lib_var=`echo tinfo'_'tgetent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ltinfo $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1182 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent(); + +int main() { +tgetent() +; return 0; } +EOF +if { (eval echo configure:1193: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo tinfo | sed -e 's/[^a-zA-Z0-9_]/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-ltinfo $LIBS" + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for tgetent in -ltermcap""... $ac_c" 1>&6 +echo "configure:1219: checking for tgetent in -ltermcap" >&5 +ac_lib_var=`echo termcap'_'tgetent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ltermcap $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1227 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent(); + +int main() { +tgetent() +; return 0; } +EOF +if { (eval echo configure:1238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo termcap | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-ltermcap $LIBS" + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for tgetent in -lcurses""... $ac_c" 1>&6 +echo "configure:1264: checking for tgetent in -lcurses" >&5 +ac_lib_var=`echo curses'_'tgetent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lcurses $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1272 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent(); + +int main() { +tgetent() +; return 0; } +EOF +if { (eval echo configure:1283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo curses | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lcurses $LIBS" + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for tgetent in -lncurses""... $ac_c" 1>&6 +echo "configure:1309: checking for tgetent in -lncurses" >&5 +ac_lib_var=`echo ncurses'_'tgetent | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lncurses $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1317 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char tgetent(); + +int main() { +tgetent() +; return 0; } +EOF +if { (eval echo configure:1328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo ncurses | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lncurses $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +fi + +fi + +fi + + +echo $ac_n "checking for library containing el_init""... $ac_c" 1>&6 +echo "configure:1363: checking for library containing el_init" >&5 +if eval "test \"`echo '$''{'ac_cv_search_el_init'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_func_search_save_LIBS="$LIBS" +ac_cv_search_el_init="no" +cat > conftest.$ac_ext <<EOF +#line 1370 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char el_init(); + +int main() { +el_init() +; return 0; } +EOF +if { (eval echo configure:1381: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_el_init="none required" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +test "$ac_cv_search_el_init" = "no" && for i in edit; do +LIBS="-l$i $ac_func_search_save_LIBS" +cat > conftest.$ac_ext <<EOF +#line 1392 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char el_init(); + +int main() { +el_init() +; return 0; } +EOF +if { (eval echo configure:1403: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ac_cv_search_el_init="-l$i" +break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done +LIBS="$ac_func_search_save_LIBS" +fi + +echo "$ac_t""$ac_cv_search_el_init" 1>&6 +if test "$ac_cv_search_el_init" != "no"; then + test "$ac_cv_search_el_init" = "none required" || LIBS="$ac_cv_search_el_init $LIBS" + have_libedit=yes +else : + have_libedit=no +fi +fi + + # Most operating systems have gethostbyname() in the default searched + # libraries (i.e. libc): + echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 +echo "configure:1428: checking for gethostbyname" >&5 +if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1433 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gethostbyname(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname) +choke me +#else +gethostbyname(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1456: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_gethostbyname=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_gethostbyname=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +# Some OSes (eg. Solaris) place it in libnsl: + echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 +echo "configure:1475: checking for gethostbyname in -lnsl" >&5 +ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lnsl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1483 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { +gethostbyname() +; return 0; } +EOF +if { (eval echo configure:1494: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lnsl $LIBS" + +else + echo "$ac_t""no" 1>&6 +# Some strange OSes (SINIX) have it in libsocket: + echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6 +echo "configure:1521: checking for gethostbyname in -lsocket" >&5 +ac_lib_var=`echo socket'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1529 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { +gethostbyname() +; return 0; } +EOF +if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lsocket $LIBS" + +else + echo "$ac_t""no" 1>&6 +# Unfortunately libsocket sometimes depends on libnsl. + # AC_CHECK_LIB's API is essentially broken so the following + # ugliness is necessary: + echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6 +echo "configure:1569: checking for gethostbyname in -lsocket" >&5 +ac_lib_var=`echo socket'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket -lnsl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1577 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { +gethostbyname() +; return 0; } +EOF +if { (eval echo configure:1588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="-lsocket -lnsl $LIBS" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for gethostbyname in -lresolv""... $ac_c" 1>&6 +echo "configure:1607: checking for gethostbyname in -lresolv" >&5 +ac_lib_var=`echo resolv'_'gethostbyname | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lresolv $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1615 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gethostbyname(); + +int main() { +gethostbyname() +; return 0; } +EOF +if { (eval echo configure:1626: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo resolv | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lresolv $LIBS" + +else + echo "$ac_t""no" 1>&6 +fi + +fi + + +fi + + +fi + + +fi + + echo $ac_n "checking for socket""... $ac_c" 1>&6 +echo "configure:1665: checking for socket" >&5 +if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1670 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char socket(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_socket) || defined (__stub___socket) +choke me +#else +socket(); +#endif + +; return 0; } +EOF +if { (eval echo configure:1693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_socket=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_socket=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 +echo "configure:1711: checking for socket in -lsocket" >&5 +ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1719 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket(); + +int main() { +socket() +; return 0; } +EOF +if { (eval echo configure:1730: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/^a-zA-Z0-9_/_/g' \ + -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'` + cat >> confdefs.h <<EOF +#define $ac_tr_lib 1 +EOF + + LIBS="-lsocket $LIBS" + +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 +echo "configure:1756: checking for socket in -lsocket" >&5 +ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocket -lnsl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1764 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char socket(); + +int main() { +socket() +; return 0; } +EOF +if { (eval echo configure:1775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="-lsocket -lnsl $LIBS" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +fi + + + + echo $ac_n "checking whether to support SOCKS""... $ac_c" 1>&6 +echo "configure:1802: checking whether to support SOCKS" >&5 + # Check whether --with-socks or --without-socks was given. +if test "${with_socks+set}" = set; then + withval="$with_socks" + + case "$withval" in + no) + echo "$ac_t""no" 1>&6 + ;; + yes) + echo "$ac_t""yes" 1>&6 + echo $ac_n "checking for SOCKSconnect in -lsocks5""... $ac_c" 1>&6 +echo "configure:1814: checking for SOCKSconnect in -lsocks5" >&5 +ac_lib_var=`echo socks5'_'SOCKSconnect | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocks5 $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1822 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char SOCKSconnect(); + +int main() { +SOCKSconnect() +; return 0; } +EOF +if { (eval echo configure:1833: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + + socks=5 + LIBS="-lsocks5 $LIBS" +else + echo "$ac_t""no" 1>&6 + + echo $ac_n "checking for Rconnect in -lsocks""... $ac_c" 1>&6 +echo "configure:1855: checking for Rconnect in -lsocks" >&5 +ac_lib_var=`echo socks'_'Rconnect | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lsocks $LIBS" +cat > conftest.$ac_ext <<EOF +#line 1863 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char Rconnect(); + +int main() { +Rconnect() +; return 0; } +EOF +if { (eval echo configure:1874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + + socks=4 + LIBS="-lsocks $LIBS" +else + echo "$ac_t""no" 1>&6 + + { echo "configure: error: Could not find socks library. You must first install socks." 1>&2; exit 1; } +fi + +fi + + ;; + esac + +else + echo "$ac_t""no" 1>&6 + +fi + + + if test "x$socks" = "x"; then + echo $ac_n "checking whether to support SOCKS5""... $ac_c" 1>&6 +echo "configure:1911: checking whether to support SOCKS5" >&5 + # Check whether --with-socks5 or --without-socks5 was given. +if test "${with_socks5+set}" = set; then + withval="$with_socks5" + + case "$withval" in + no) + echo "$ac_t""no" 1>&6 + ;; + *) + echo "$ac_t""yes" 1>&6 + socks=5 + if test "x$withval" = "xyes"; then + withval="-lsocks5" + else + if test -d "$withval"; then + if test -d "$withval/include"; then + CFLAGS="$CFLAGS -I$withval/include" + else + CFLAGS="$CFLAGS -I$withval" + fi + if test -d "$withval/lib"; then + withval="-L$withval/lib -lsocks5" + else + withval="-L$withval -lsocks5" + fi + fi + fi + LIBS="$withval $LIBS" + # If Socks was compiled with Kerberos support, we will need + # to link against kerberos libraries. Temporarily append + # to LIBS. This is harmless if there is no kerberos support. + TMPLIBS="$LIBS" + LIBS="$LIBS $KERBEROS_LIBS" + cat > conftest.$ac_ext <<EOF +#line 1946 "configure" +#include "confdefs.h" + +int main() { + SOCKSconnect(); +; return 0; } +EOF +if { (eval echo configure:1953: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + { echo "configure: error: Could not find the $withval library. You must first install socks5." 1>&2; exit 1; } +fi +rm -f conftest* + LIBS="$TMPLIBS" + ;; + esac + +else + echo "$ac_t""no" 1>&6 + +fi + + fi + + if test "x$socks" = "x"; then + echo $ac_n "checking whether to support SOCKS4""... $ac_c" 1>&6 +echo "configure:1975: checking whether to support SOCKS4" >&5 + # Check whether --with-socks4 or --without-socks4 was given. +if test "${with_socks4+set}" = set; then + withval="$with_socks4" + + case "$withval" in + no) + echo "$ac_t""no" 1>&6 + ;; + *) + echo "$ac_t""yes" 1>&6 + socks=4 + if test "x$withval" = "xyes"; then + withval="-lsocks" + else + if test -d "$withval"; then + withval="-L$withval -lsocks" + fi + fi + LIBS="$withval $LIBS" + cat > conftest.$ac_ext <<EOF +#line 1996 "configure" +#include "confdefs.h" + +int main() { + Rconnect(); +; return 0; } +EOF +if { (eval echo configure:2003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + { echo "configure: error: Could not find the $withval library. You must first install socks." 1>&2; exit 1; } +fi +rm -f conftest* + ;; + esac + +else + echo "$ac_t""no" 1>&6 + +fi + + fi + + if test "x$socks" = "x4"; then + cat >> confdefs.h <<\EOF +#define SOCKS 1 +EOF + + cat >> confdefs.h <<\EOF +#define SOCKS4 1 +EOF + + cat >> confdefs.h <<\EOF +#define connect Rconnect +EOF + + cat >> confdefs.h <<\EOF +#define getsockname Rgetsockname +EOF + + cat >> confdefs.h <<\EOF +#define bind Rbind +EOF + + cat >> confdefs.h <<\EOF +#define accept Raccept +EOF + + cat >> confdefs.h <<\EOF +#define listen Rlisten +EOF + + cat >> confdefs.h <<\EOF +#define select Rselect +EOF + + fi + + if test "x$socks" = "x5"; then + cat >> confdefs.h <<\EOF +#define SOCKS 1 +EOF + + cat >> confdefs.h <<\EOF +#define SOCKS5 1 +EOF + + cat >> confdefs.h <<\EOF +#define connect SOCKSconnect +EOF + + cat >> confdefs.h <<\EOF +#define getsockname SOCKSgetsockname +EOF + + cat >> confdefs.h <<\EOF +#define getpeername SOCKSgetpeername +EOF + + cat >> confdefs.h <<\EOF +#define bind SOCKSbind +EOF + + cat >> confdefs.h <<\EOF +#define accept SOCKSaccept +EOF + + cat >> confdefs.h <<\EOF +#define listen SOCKSlisten +EOF + + cat >> confdefs.h <<\EOF +#define select SOCKSselect +EOF + + cat >> confdefs.h <<\EOF +#define recvfrom SOCKSrecvfrom +EOF + + cat >> confdefs.h <<\EOF +#define sendto SOCKSsendto +EOF + + cat >> confdefs.h <<\EOF +#define recv SOCKSrecv +EOF + + cat >> confdefs.h <<\EOF +#define send SOCKSsend +EOF + + cat >> confdefs.h <<\EOF +#define read SOCKSread +EOF + + cat >> confdefs.h <<\EOF +#define write SOCKSwrite +EOF + + cat >> confdefs.h <<\EOF +#define rresvport SOCKSrresvport +EOF + + cat >> confdefs.h <<\EOF +#define shutdown SOCKSshutdown +EOF + + cat >> confdefs.h <<\EOF +#define listen SOCKSlisten +EOF + + cat >> confdefs.h <<\EOF +#define close SOCKSclose +EOF + + cat >> confdefs.h <<\EOF +#define dup SOCKSdup +EOF + + cat >> confdefs.h <<\EOF +#define dup2 SOCKSdup2 +EOF + + cat >> confdefs.h <<\EOF +#define fclose SOCKSfclose +EOF + + cat >> confdefs.h <<\EOF +#define gethostbyname SOCKSgethostbyname +EOF + + fi + +if test -n "$socks"; then + if test $opt_ipv6 = yes; then + echo "IPv6 is incompatible with socks, disabling IPv6 support" + opt_ipv6=no + fi +fi + + + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6 +echo "configure:2166: checking for $ac_hdr that defines DIR" >&5 +if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2171 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <$ac_hdr> +int main() { +DIR *dirp = 0; +; return 0; } +EOF +if { (eval echo configure:2179: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_dirent_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + ac_header_dirent=$ac_hdr; break +else + echo "$ac_t""no" 1>&6 +fi +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then +echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6 +echo "configure:2204: checking for opendir in -ldir" >&5 +ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldir $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2212 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir(); + +int main() { +opendir() +; return 0; } +EOF +if { (eval echo configure:2223: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -ldir" +else + echo "$ac_t""no" 1>&6 +fi + +else +echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 +echo "configure:2245: checking for opendir in -lx" >&5 +ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-lx $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2253 "configure" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char opendir(); + +int main() { +opendir() +; return 0; } +EOF +if { (eval echo configure:2264: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + LIBS="$LIBS -lx" +else + echo "$ac_t""no" 1>&6 +fi + +fi + +echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:2287: checking for ANSI C header files" >&5 +if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2292 "configure" +#include "confdefs.h" +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2300: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + ac_cv_header_stdc=yes +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 2317 "configure" +#include "confdefs.h" +#include <string.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "memchr" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. +cat > conftest.$ac_ext <<EOF +#line 2335 "configure" +#include "confdefs.h" +#include <stdlib.h> +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "free" >/dev/null 2>&1; then + : +else + rm -rf conftest* + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. +if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 2356 "configure" +#include "confdefs.h" +#include <ctype.h> +#define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int main () { int i; for (i = 0; i < 256; i++) +if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); +exit (0); } + +EOF +if { (eval echo configure:2367: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + : +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_header_stdc=no +fi +rm -fr conftest* +fi + +fi +fi + +echo "$ac_t""$ac_cv_header_stdc" 1>&6 +if test $ac_cv_header_stdc = yes; then + cat >> confdefs.h <<\EOF +#define STDC_HEADERS 1 +EOF + +fi + +for ac_hdr in arpa/nameser.h err.h regex.h paths.h poll.h sys/poll.h \ + termcap.h util.h libutil.h vis.h +do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "configure:2395: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2400 "configure" +#include "confdefs.h" +#include <$ac_hdr> +EOF +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:2405: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'` + cat >> confdefs.h <<EOF +#define $ac_tr_hdr 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + + + +echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 +echo "configure:2434: checking whether time.h and sys/time.h may both be included" >&5 +if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2439 "configure" +#include "confdefs.h" +#include <sys/types.h> +#include <sys/time.h> +#include <time.h> +int main() { +struct tm *tp; +; return 0; } +EOF +if { (eval echo configure:2448: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_header_time=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_header_time=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_header_time" 1>&6 +if test $ac_cv_header_time = yes; then + cat >> confdefs.h <<\EOF +#define TIME_WITH_SYS_TIME 1 +EOF + +fi + +echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:2469: checking for off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2474 "configure" +#include "confdefs.h" +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +EOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_type_off_t=yes +else + rm -rf conftest* + ac_cv_type_off_t=no +fi +rm -f conftest* + +fi +echo "$ac_t""$ac_cv_type_off_t" 1>&6 +if test $ac_cv_type_off_t = no; then + cat >> confdefs.h <<\EOF +#define off_t long +EOF + +fi + +echo $ac_n "checking size of off_t""... $ac_c" 1>&6 +echo "configure:2502: checking size of off_t" >&5 +if eval "test \"`echo '$''{'ac_cv_sizeof_off_t'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + ac_cv_sizeof_off_t=0 +else + cat > conftest.$ac_ext <<EOF +#line 2510 "configure" +#include "confdefs.h" +#include <stdio.h> +main() +{ + FILE *f=fopen("conftestval", "w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof(off_t)); + exit(0); +} +EOF +if { (eval echo configure:2521: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_sizeof_off_t=`cat conftestval` +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_sizeof_off_t=0 +fi +rm -fr conftest* +fi + +fi +echo "$ac_t""$ac_cv_sizeof_off_t" 1>&6 +cat >> confdefs.h <<EOF +#define SIZEOF_OFF_T $ac_cv_sizeof_off_t +EOF + + + + echo $ac_n "checking for long long""... $ac_c" 1>&6 +echo "configure:2542: checking for long long" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_LONG_LONG'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2548 "configure" +#include "confdefs.h" + +#include <sys/types.h> +int main() { + +long long X = 2, Y = 1, Z; +Z = X / Y; ; +; return 0; } +EOF +if { (eval echo configure:2558: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + ftp_cv_HAVE_LONG_LONG=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_LONG_LONG=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_LONG_LONG" 1>&6 + if test "x$ftp_cv_HAVE_LONG_LONG" = "xyes"; then + +cat >> confdefs.h <<\EOF +#define HAVE_LONG_LONG 1 +EOF + +have_long_long=yes + else + have_long_long=no + : + fi + + + + echo $ac_n "checking for in_port_t""... $ac_c" 1>&6 +echo "configure:2587: checking for in_port_t" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_IN_PORT_T'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2593 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <netinet/in.h> +int main() { + in_port_t X ; +; return 0; } +EOF +if { (eval echo configure:2602: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_IN_PORT_T=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_IN_PORT_T=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_IN_PORT_T" 1>&6 + if test "x$ftp_cv_HAVE_IN_PORT_T" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_IN_PORT_T 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for sa_family_t""... $ac_c" 1>&6 +echo "configure:2629: checking for sa_family_t" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_SA_FAMILY_T'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2635 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <sys/socket.h> +int main() { + sa_family_t X ; +; return 0; } +EOF +if { (eval echo configure:2644: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_SA_FAMILY_T=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_SA_FAMILY_T=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_SA_FAMILY_T" 1>&6 + if test "x$ftp_cv_HAVE_SA_FAMILY_T" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SA_FAMILY_T 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for sockaddr_in.sin_len""... $ac_c" 1>&6 +echo "configure:2671: checking for sockaddr_in.sin_len" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_SOCKADDR_SA_LEN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2677 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +int main() { + + struct sockaddr_in sin; + int X = sin.sin_len ; +; return 0; } +EOF +if { (eval echo configure:2689: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_SOCKADDR_SA_LEN=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_SOCKADDR_SA_LEN=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_SOCKADDR_SA_LEN" 1>&6 + if test "x$ftp_cv_HAVE_SOCKADDR_SA_LEN" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SOCKADDR_SA_LEN 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for socklen_t""... $ac_c" 1>&6 +echo "configure:2716: checking for socklen_t" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_SOCKLEN_T'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2722 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <sys/socket.h> +int main() { + socklen_t X ; +; return 0; } +EOF +if { (eval echo configure:2731: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_SOCKLEN_T=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_SOCKLEN_T=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_SOCKLEN_T" 1>&6 + if test "x$ftp_cv_HAVE_SOCKLEN_T" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SOCKLEN_T 1 +EOF + + else + + : + fi + + +if test $opt_ipv6 = yes; then + + + echo $ac_n "checking for AF_INET6""... $ac_c" 1>&6 +echo "configure:2760: checking for AF_INET6" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_AF_INET6'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2766 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <sys/socket.h> +int main() { + int X = AF_INET6 ; +; return 0; } +EOF +if { (eval echo configure:2775: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_AF_INET6=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_AF_INET6=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_AF_INET6" 1>&6 + if test "x$ftp_cv_HAVE_AF_INET6" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_AF_INET6 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for struct sockaddr_in6""... $ac_c" 1>&6 +echo "configure:2802: checking for struct sockaddr_in6" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_SOCKADDR_IN6'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2808 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <netinet/in.h> +int main() { + struct sockaddr_in6 X ; +; return 0; } +EOF +if { (eval echo configure:2817: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_SOCKADDR_IN6=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_SOCKADDR_IN6=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_SOCKADDR_IN6" 1>&6 + if test "x$ftp_cv_HAVE_SOCKADDR_IN6" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_SOCKADDR_IN6 1 +EOF + + else + + : + fi + + +fi + + + echo $ac_n "checking for struct addrinfo""... $ac_c" 1>&6 +echo "configure:2846: checking for struct addrinfo" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_ADDRINFO'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2852 "configure" +#include "confdefs.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +int main() { + struct addrinfo X ; +; return 0; } +EOF +if { (eval echo configure:2862: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_ADDRINFO=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_ADDRINFO=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_ADDRINFO" 1>&6 + if test "x$ftp_cv_HAVE_ADDRINFO" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_ADDRINFO 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for d_namlen in struct dirent""... $ac_c" 1>&6 +echo "configure:2889: checking for d_namlen in struct dirent" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_D_NAMLEN'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2895 "configure" +#include "confdefs.h" + +#if HAVE_DIRENT_H +# include <dirent.h> +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif +int main() { + + struct dirent dp; + int X = dp.d_namlen; ; +; return 0; } +EOF +if { (eval echo configure:2918: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_D_NAMLEN=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_D_NAMLEN=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_D_NAMLEN" 1>&6 + if test "x$ftp_cv_HAVE_D_NAMLEN" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_D_NAMLEN 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for h_errno declaration""... $ac_c" 1>&6 +echo "configure:2945: checking for h_errno declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_H_ERRNO_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2951 "configure" +#include "confdefs.h" + +#include <netdb.h> +int main() { + int X = h_errno ; +; return 0; } +EOF +if { (eval echo configure:2959: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_H_ERRNO_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_H_ERRNO_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_H_ERRNO_D" 1>&6 + if test "x$ftp_cv_HAVE_H_ERRNO_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_H_ERRNO_D 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for fclose() declaration""... $ac_c" 1>&6 +echo "configure:2986: checking for fclose() declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_FCLOSE_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 2992 "configure" +#include "confdefs.h" + +#include <stdio.h> +int main() { + int (*X)() = fclose ; +; return 0; } +EOF +if { (eval echo configure:3000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_FCLOSE_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_FCLOSE_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_FCLOSE_D" 1>&6 + if test "x$ftp_cv_HAVE_FCLOSE_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_FCLOSE_D 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for getpass() declaration""... $ac_c" 1>&6 +echo "configure:3027: checking for getpass() declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_GETPASS_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3033 "configure" +#include "confdefs.h" + +#include <stdlib.h> +#include <unistd.h> +int main() { + char *(*X)() = getpass ; +; return 0; } +EOF +if { (eval echo configure:3042: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_GETPASS_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_GETPASS_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_GETPASS_D" 1>&6 + if test "x$ftp_cv_HAVE_GETPASS_D" = "xyes"; then + + cat >> confdefs.h <<\EOF +#define HAVE_GETPASS_D 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for optarg declaration""... $ac_c" 1>&6 +echo "configure:3070: checking for optarg declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_OPTARG_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3076 "configure" +#include "confdefs.h" + +#include <stdlib.h> +#include <unistd.h> +int main() { + char *X = optarg ; +; return 0; } +EOF +if { (eval echo configure:3085: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_OPTARG_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_OPTARG_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_OPTARG_D" 1>&6 + if test "x$ftp_cv_HAVE_OPTARG_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_OPTARG_D 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for optind declaration""... $ac_c" 1>&6 +echo "configure:3112: checking for optind declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_OPTIND_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3118 "configure" +#include "confdefs.h" + +#include <stdlib.h> +#include <unistd.h> +int main() { + int X = optind ; +; return 0; } +EOF +if { (eval echo configure:3127: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_OPTIND_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_OPTIND_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_OPTIND_D" 1>&6 + if test "x$ftp_cv_HAVE_OPTIND_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_OPTIND_D 1 +EOF + + else + + : + fi + + + + echo $ac_n "checking for pclose() declaration""... $ac_c" 1>&6 +echo "configure:3154: checking for pclose() declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_PCLOSE_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3160 "configure" +#include "confdefs.h" + +#include <stdio.h> +int main() { + int (*X)() = pclose ; +; return 0; } +EOF +if { (eval echo configure:3168: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_PCLOSE_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_PCLOSE_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_PCLOSE_D" 1>&6 + if test "x$ftp_cv_HAVE_PCLOSE_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_PCLOSE_D 1 +EOF + + else + + : + fi + + + +for ac_func in err fgetln fseeko getaddrinfo getnameinfo inet_ntop inet_pton \ + mkstemp setprogname sl_init snprintf strdup strerror strlcat \ + strlcpy strptime strsep strunvis strvis timegm usleep +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3199: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3204 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3227: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}" +fi +done + + +for ac_func in gethostbyname2 getpassphrase getpgrp memmove poll select +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3256: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3261 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3284: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +fi +done + +if test $ac_cv_func_getpgrp = yes; then + echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 +echo "configure:3310: checking whether getpgrp takes no argument" >&5 +if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + { echo "configure: error: cannot check getpgrp if cross compiling" 1>&2; exit 1; } +else + cat > conftest.$ac_ext <<EOF +#line 3318 "configure" +#include "confdefs.h" + +/* + * If this system has a BSD-style getpgrp(), + * which takes a pid argument, exit unsuccessfully. + * + * Snarfed from Chet Ramey's bash pgrp.c test program + */ +#include <stdio.h> +#include <sys/types.h> + +int pid; +int pg1, pg2, pg3, pg4; +int ng, np, s, child; + +main() +{ + pid = getpid(); + pg1 = getpgrp(0); + pg2 = getpgrp(); + pg3 = getpgrp(pid); + pg4 = getpgrp(1); + + /* + * If all of these values are the same, it's pretty sure that + * we're on a system that ignores getpgrp's first argument. + */ + if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3) + exit(0); + + child = fork(); + if (child < 0) + exit(1); + else if (child == 0) { + np = getpid(); + /* + * If this is Sys V, this will not work; pgrp will be + * set to np because setpgrp just changes a pgrp to be + * the same as the pid. + */ + setpgrp(np, pg1); + ng = getpgrp(0); /* Same result for Sys V and BSD */ + if (ng == pg1) { + exit(1); + } else { + exit(0); + } + } else { + wait(&s); + exit(s>>8); + } +} + +EOF +if { (eval echo configure:3373: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + ac_cv_func_getpgrp_void=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + ac_cv_func_getpgrp_void=no +fi +rm -fr conftest* +fi + + +fi + +echo "$ac_t""$ac_cv_func_getpgrp_void" 1>&6 +if test $ac_cv_func_getpgrp_void = yes; then + cat >> confdefs.h <<\EOF +#define GETPGRP_VOID 1 +EOF + +fi + +fi +if test $ac_cv_lib_util_fparseln != yes; then + for ac_func in fparseln +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3401: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3406 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}" +fi +done + + +fi + +LIBOBJS="$LIBOBJS glob.o" + +if test $ac_cv_func_strptime = yes; then + + echo $ac_n "checking for strptime() declaration""... $ac_c" 1>&6 +echo "configure:3462: checking for strptime() declaration" >&5 +if eval "test \"`echo '$''{'ftp_cv_HAVE_STRPTIME_D'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3468 "configure" +#include "confdefs.h" + + #include <time.h> +int main() { + char *X = strptime("", "", NULL) ; +; return 0; } +EOF +if { (eval echo configure:3476: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_HAVE_STRPTIME_D=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_HAVE_STRPTIME_D=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_HAVE_STRPTIME_D" 1>&6 + if test "x$ftp_cv_HAVE_STRPTIME_D" = "xyes"; then + cat >> confdefs.h <<\EOF +#define HAVE_STRPTIME_D 1 +EOF + + else + + : + fi + +fi + +if test $have_long_long = yes -a $ac_cv_sizeof_off_t -ge 8; then + + + echo $ac_n "checking *printf() support for %lld""... $ac_c" 1>&6 +echo "configure:3506: checking *printf() support for %lld" >&5 + can_printf_longlong=no + if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 3512 "configure" +#include "confdefs.h" + + #include <stdio.h> + int main() { + char buf[100]; + sprintf(buf, "%lld", 4294967300LL); + return (strcmp(buf, "4294967300")); + } + +EOF +if { (eval echo configure:3523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + + echo "$ac_t""yes" 1>&6 + can_printf_longlong=yes + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + + echo "$ac_t""no" 1>&6 + +fi +rm -fr conftest* +fi + + + if test $can_printf_longlong != yes; then + echo $ac_n "checking *printf() support for %qd""... $ac_c" 1>&6 +echo "configure:3543: checking *printf() support for %qd" >&5 + if test "$cross_compiling" = yes; then + : +else + cat > conftest.$ac_ext <<EOF +#line 3548 "configure" +#include "confdefs.h" + + #include <stdio.h> + int main() { + char buf[100]; + sprintf(buf, "%qd", 4294967300LL); + return (strcmp(buf, "4294967300")); + } + +EOF +if { (eval echo configure:3559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +then + + echo "$ac_t""yes" 1>&6 + can_printf_longlong=yes + cat >> confdefs.h <<\EOF +#define HAVE_PRINTF_QD 1 +EOF + + +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + + echo "$ac_t""no" 1>&6 + +fi +rm -fr conftest* +fi + + fi + + if test $can_printf_longlong = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_QUAD_SUPPORT 1 +EOF + + for ac_func in strtoll +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3590: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 3595 "configure" +#include "confdefs.h" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3618: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <<EOF +#define $ac_tr_func 1 +EOF + +else + echo "$ac_t""no" 1>&6 +LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}" +fi +done + + + fi + +fi + + +if test $opt_editcomplete = yes; then + if test $have_libedit = yes; then + + echo $ac_n "checking for EL_RPROMPT in libedit""... $ac_c" 1>&6 +echo "configure:3653: checking for EL_RPROMPT in libedit" >&5 +if eval "test \"`echo '$''{'ftp_cv_have_libedit'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3659 "configure" +#include "confdefs.h" + + #include <histedit.h> +int main() { + int X = EL_RPROMPT ; +; return 0; } +EOF +if { (eval echo configure:3667: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_have_libedit=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_have_libedit=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_have_libedit" 1>&6 + if test "x$ftp_cv_have_libedit" = "xyes"; then + : + else + have_libedit=no + : + fi + + fi + + echo $ac_n "checking for working libedit""... $ac_c" 1>&6 +echo "configure:3691: checking for working libedit" >&5 + if test $have_libedit = no; then + echo "$ac_t""no - using my own" 1>&6 + INCLUDES="-I\${srcdir}/../libedit $INCLUDES" + LDFLAGS="-L../libedit $LDFLAGS" + LIBS="-ledit $LIBS" + LIBEDIT=libedit.a + LIBDEPENDS="$LIBDEPENDS ../libedit/libedit.a" + else + echo "$ac_t""yes" 1>&6 + fi +else + CFLAGS="-DNO_EDITCOMPLETE $CFLAGS" +fi + +if test $ac_cv_func_sl_init = yes; then + + echo $ac_n "checking if sl_add() returns int""... $ac_c" 1>&6 +echo "configure:3709: checking if sl_add() returns int" >&5 +if eval "test \"`echo '$''{'ftp_cv_INT_SL_ADD'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3715 "configure" +#include "confdefs.h" + + #include <stringlist.h> +int main() { + int f = sl_add((StringList *)0, "foo") ; +; return 0; } +EOF +if { (eval echo configure:3723: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_INT_SL_ADD=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_INT_SL_ADD=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_INT_SL_ADD" 1>&6 + if test "x$ftp_cv_INT_SL_ADD" = "xyes"; then + : + else + LIBOBJS="$LIBOBJS sl_init.o" + : + fi + +fi + + +have_rfc2553_netdb=no +if test $ac_cv_func_getaddrinfo = yes -a ! -n "$socks"; then + + echo $ac_n "checking for AI_NUMERICHOST""... $ac_c" 1>&6 +echo "configure:3751: checking for AI_NUMERICHOST" >&5 +if eval "test \"`echo '$''{'ftp_cv_have_ai_numerichost'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3757 "configure" +#include "confdefs.h" + + #include <sys/types.h> + #include <sys/socket.h> + #include <netdb.h> +int main() { + int X = AI_NUMERICHOST ; +; return 0; } +EOF +if { (eval echo configure:3767: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_have_ai_numerichost=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_have_ai_numerichost=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_have_ai_numerichost" 1>&6 + if test "x$ftp_cv_have_ai_numerichost" = "xyes"; then + have_rfc2553_netdb=yes + else + + : + fi + +fi +echo $ac_n "checking for working getaddrinfo()""... $ac_c" 1>&6 +echo "configure:3790: checking for working getaddrinfo()" >&5 +if test $have_rfc2553_netdb = yes; then + cat >> confdefs.h <<\EOF +#define HAVE_RFC2553_NETDB 1 +EOF + + echo "$ac_t""yes" 1>&6 +else + if test $ac_cv_func_getaddrinfo = yes; then + LIBOBJS="$LIBOBJS getaddrinfo.o" + echo "$ac_t""no - using local version" 1>&6 + else + echo "$ac_t""using local version" 1>&6 + fi +fi + + +if test $ac_cv_header_vis_h = yes; then + + echo $ac_n "checking for VIS_WHITE in vis.h""... $ac_c" 1>&6 +echo "configure:3810: checking for VIS_WHITE in vis.h" >&5 +if eval "test \"`echo '$''{'ftp_cv_have_vis_white'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + + cat > conftest.$ac_ext <<EOF +#line 3816 "configure" +#include "confdefs.h" + + #include <sys/types.h> + #include <vis.h> +int main() { + int X = VIS_WHITE ; +; return 0; } +EOF +if { (eval echo configure:3825: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ftp_cv_have_vis_white=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ftp_cv_have_vis_white=no +fi +rm -f conftest* + +fi + +echo "$ac_t""$ftp_cv_have_vis_white" 1>&6 + if test "x$ftp_cv_have_vis_white" = "xyes"; then + : + else + ac_cv_header_vis_h=no + : + fi + +fi + + +if test -n "$LIBOBJS"; then + INCLUDES="$INCLUDES -I\${srcdir}/../libukem" + LDFLAGS="$LDFLAGS -L../libukem" + LIBS="$LIBS -lukem" + LIBUKEM=libukem.a + LIBDEPENDS="$LIBDEPENDS ../libukem/libukem.a" +fi + + + + + + + +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Any assignment to VPATH causes Sun make to only execute +# the first set of double-colon rules, so remove it if not needed. +# If there is a colon in the path, we need to keep it. +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' +fi + +trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 + +DEFS=-DHAVE_CONFIG_H + +# Without the "./", some shells look in PATH for config.status. +: ${CONFIG_STATUS=./config.status} + +echo creating $CONFIG_STATUS +rm -f $CONFIG_STATUS +cat > $CONFIG_STATUS <<EOF +#! /bin/sh +# Generated automatically by configure. +# Run this file to recreate the current configuration. +# This directory was configured as follows, +# on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# $0 $ac_configure_args +# +# Compiler output produced by configure, useful for debugging +# configure, is in ./config.log if it exists. + +ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" +for ac_option +do + case "\$ac_option" in + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" + exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; + -version | --version | --versio | --versi | --vers | --ver | --ve | --v) + echo "$CONFIG_STATUS generated by autoconf version 2.13" + exit 0 ;; + -help | --help | --hel | --he | --h) + echo "\$ac_cs_usage"; exit 0 ;; + *) echo "\$ac_cs_usage"; exit 1 ;; + esac +done + +ac_given_srcdir=$srcdir +ac_given_INSTALL="$INSTALL" + +trap 'rm -fr `echo "Makefile libedit/Makefile libedit/makelist libukem/Makefile \ + src/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF + +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF +$ac_vpsub +$extrasub +s%@SHELL@%$SHELL%g +s%@CFLAGS@%$CFLAGS%g +s%@CPPFLAGS@%$CPPFLAGS%g +s%@CXXFLAGS@%$CXXFLAGS%g +s%@FFLAGS@%$FFLAGS%g +s%@DEFS@%$DEFS%g +s%@LDFLAGS@%$LDFLAGS%g +s%@LIBS@%$LIBS%g +s%@exec_prefix@%$exec_prefix%g +s%@prefix@%$prefix%g +s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g +s%@SET_MAKE@%$SET_MAKE%g +s%@CC@%$CC%g +s%@AWK@%$AWK%g +s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g +s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g +s%@INSTALL_DATA@%$INSTALL_DATA%g +s%@RANLIB@%$RANLIB%g +s%@AR@%$AR%g +s%@CPP@%$CPP%g +s%@LIBOBJS@%$LIBOBJS%g +s%@INCLUDES@%$INCLUDES%g +s%@LIBEDIT@%$LIBEDIT%g +s%@LIBUKEM@%$LIBUKEM%g +s%@LIBDEPENDS@%$LIBDEPENDS%g + +CEOF +EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + +cat >> $CONFIG_STATUS <<EOF + +CONFIG_FILES=\${CONFIG_FILES-"Makefile libedit/Makefile libedit/makelist libukem/Makefile \ + src/Makefile"} +EOF +cat >> $CONFIG_STATUS <<\EOF +for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. + + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" + # A "../" for each directory in $ac_dir_suffix. + ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` + else + ac_dir_suffix= ac_dots= + fi + + case "$ac_given_srcdir" in + .) srcdir=. + if test -z "$ac_dots"; then top_srcdir=. + else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; + /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; + *) # Relative path. + srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" + top_srcdir="$ac_dots$ac_given_srcdir" ;; + esac + + case "$ac_given_INSTALL" in + [/$]*) INSTALL="$ac_given_INSTALL" ;; + *) INSTALL="$ac_dots$ac_given_INSTALL" ;; + esac + + echo creating "$ac_file" + rm -f "$ac_file" + configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." + case "$ac_file" in + *Makefile*) ac_comsub="1i\\ +# $configure_input" ;; + *) ac_comsub= ;; + esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + sed -e "$ac_comsub +s%@configure_input@%$configure_input%g +s%@srcdir@%$srcdir%g +s%@top_srcdir@%$top_srcdir%g +s%@INSTALL@%$INSTALL%g +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file +fi; done +rm -f conftest.s* + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='\([ ][ ]*\)[^ ]*%\1#\2' +ac_dC='\3' +ac_dD='%g' +# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE". +ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='\([ ]\)%\1#\2define\3' +ac_uC=' ' +ac_uD='\4%g' +# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_eB='$%\1#\2define\3' +ac_eC=' ' +ac_eD='%g' + +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="config.h" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi +for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case "$ac_file" in + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` + ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; + *) ac_file_in="${ac_file}.in" ;; + esac + + echo creating $ac_file + + rm -f conftest.frag conftest.in conftest.out + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in + +EOF + +# Transform confdefs.h into a sed script conftest.vals that substitutes +# the proper values into config.h.in to produce config.h. And first: +# Protect against being on the right side of a sed subst in config.status. +# Protect against being in an unquoted here document in config.status. +rm -f conftest.vals +cat > conftest.hdr <<\EOF +s/[\\&%]/\\&/g +s%[\\$`]%\\&%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%ac_d%ac_u%gp +s%ac_u%ac_e%gp +EOF +sed -n -f conftest.hdr confdefs.h > conftest.vals +rm -f conftest.hdr + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >> conftest.vals <<\EOF +s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */% +EOF + +# Break up conftest.vals because some shells have a limit on +# the size of here documents, and old seds have small limits too. + +rm -f conftest.tail +while : +do + ac_lines=`grep -c . conftest.vals` + # grep -c gives empty output for an empty file on some AIX systems. + if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi + # Write a limited-size here document to conftest.frag. + echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS + echo 'CEOF + sed -f conftest.frag conftest.in > conftest.out + rm -f conftest.in + mv conftest.out conftest.in +' >> $CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail + rm -f conftest.vals + mv conftest.tail conftest.vals +done +rm -f conftest.vals + +cat >> $CONFIG_STATUS <<\EOF + rm -f conftest.frag conftest.h + echo "/* $ac_file. Generated automatically by configure. */" > conftest.h + cat conftest.in >> conftest.h + rm -f conftest.in + if cmp -s $ac_file conftest.h 2>/dev/null; then + echo "$ac_file is unchanged" + rm -f conftest.h + else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi + rm -f $ac_file + mv conftest.h $ac_file + fi +fi; done + +EOF +cat >> $CONFIG_STATUS <<EOF + +EOF +cat >> $CONFIG_STATUS <<\EOF + +exit 0 +EOF +chmod +x $CONFIG_STATUS +rm -fr confdefs* $ac_clean_files +test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 + diff --git a/contrib/tnftp/configure.in b/contrib/tnftp/configure.in new file mode 100644 index 0000000..4edb841 --- /dev/null +++ b/contrib/tnftp/configure.in @@ -0,0 +1,307 @@ +dnl $Id: configure.in,v 1.37 2002/06/10 08:08:53 lukem Exp $ +dnl +dnl configure.in -- +dnl process this file with autoconf to produce a configure script. +dnl + +AC_REVISION($Revision: 1.37 $)dnl + +AC_INIT(lukemftp.h) + +dnl Arguments for which features are included +dnl +AC_ARG_PROGRAM +AC_ARG_ENABLE(editcomplete, [\ + --enable-editcomplete Turn on command line editing and completion. + --disable-editcomplete Turn off command line editing and completion + [default: enabled].], + opt_editcomplete=$enableval, + opt_editcomplete=yes) +AC_ARG_ENABLE(ipv6, [\ + --enable-ipv6 Enable IPv6 support (if your OS supports it). + --disable-ipv6 Disable IPv6 support (even if your OS supports it) + [default: enabled].], + opt_ipv6=$enableval, + opt_ipv6=yes) + +dnl Checks for programs. +dnl +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_AWK +AC_PROG_INSTALL +AC_PROG_RANLIB +AC_CHECK_PROGS(AR, ar) +AC_AIX + + +dnl Checks for libraries. +dnl +AC_CHECK_LIB(util, fparseln) +if test $opt_editcomplete = yes; then + AC_CHECK_LIB(tinfo, tgetent, , + AC_CHECK_LIB(termcap, tgetent, , + AC_CHECK_LIB(curses, tgetent, , + AC_CHECK_LIB(ncurses, tgetent)))) + AC_SEARCH_LIBS(el_init, edit, have_libedit=yes, have_libedit=no) +fi +AC_LIBRARY_NET +AC_LIBRARY_SOCKS +if test -n "$socks"; then + if test $opt_ipv6 = yes; then + echo "IPv6 is incompatible with socks, disabling IPv6 support" + opt_ipv6=no + fi +fi + + +dnl Checks for header files. +dnl +AC_CONFIG_HEADER(config.h) +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS(arpa/nameser.h err.h regex.h paths.h poll.h sys/poll.h \ + termcap.h util.h libutil.h vis.h) + + +dnl Checks for typedefs, structures, and compiler characteristics. +dnl +AC_HEADER_TIME +AC_TYPE_OFF_T +AC_CHECK_SIZEOF(off_t, 0) +AC_MSG_TRY_LINK(for long long, ftp_cv_HAVE_LONG_LONG, [ +#include <sys/types.h>] , [ +long long X = 2, Y = 1, Z; +Z = X / Y; ], [ +AC_DEFINE(HAVE_LONG_LONG, 1) +have_long_long=yes], [have_long_long=no]) + +AC_MSG_TRY_COMPILE(for in_port_t, ftp_cv_HAVE_IN_PORT_T, [ +#include <sys/types.h> +#include <netinet/in.h> ], [ in_port_t X ], [AC_DEFINE(HAVE_IN_PORT_T, 1)]) + +AC_MSG_TRY_COMPILE(for sa_family_t, ftp_cv_HAVE_SA_FAMILY_T, [ +#include <sys/types.h> +#include <sys/socket.h> ], [ sa_family_t X ], [AC_DEFINE(HAVE_SA_FAMILY_T, 1)]) + +AC_MSG_TRY_COMPILE(for sockaddr_in.sin_len, ftp_cv_HAVE_SOCKADDR_SA_LEN, [ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> ], [ + struct sockaddr_in sin; + int X = sin.sin_len ], [AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1)]) + +AC_MSG_TRY_COMPILE(for socklen_t, ftp_cv_HAVE_SOCKLEN_T, [ +#include <sys/types.h> +#include <sys/socket.h> ], [ socklen_t X ], [AC_DEFINE(HAVE_SOCKLEN_T, 1)]) + +if test $opt_ipv6 = yes; then + + AC_MSG_TRY_COMPILE(for AF_INET6, ftp_cv_HAVE_AF_INET6, [ +#include <sys/types.h> +#include <sys/socket.h> ], + [ int X = AF_INET6 ], [AC_DEFINE(HAVE_AF_INET6, 1)]) + + AC_MSG_TRY_COMPILE(for struct sockaddr_in6, ftp_cv_HAVE_SOCKADDR_IN6, [ +#include <sys/types.h> +#include <netinet/in.h> ], + [ struct sockaddr_in6 X ], [AC_DEFINE(HAVE_SOCKADDR_IN6, 1)]) + +fi + +AC_MSG_TRY_COMPILE(for struct addrinfo, ftp_cv_HAVE_ADDRINFO, [ +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> ], + [ struct addrinfo X ], [AC_DEFINE(HAVE_ADDRINFO, 1)]) + +AC_MSG_TRY_COMPILE(for d_namlen in struct dirent, ftp_cv_HAVE_D_NAMLEN, [ +#if HAVE_DIRENT_H +# include <dirent.h> +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif ], [ + struct dirent dp; + int X = dp.d_namlen; ], [AC_DEFINE(HAVE_D_NAMLEN, 1)]) + +AC_MSG_TRY_COMPILE(for h_errno declaration, ftp_cv_HAVE_H_ERRNO_D, [ +#include <netdb.h> ], [ int X = h_errno ], [AC_DEFINE(HAVE_H_ERRNO_D, 1)]) + +AC_MSG_TRY_COMPILE(for fclose() declaration, ftp_cv_HAVE_FCLOSE_D, [ +#include <stdio.h> ], [ int (*X)() = fclose ], [AC_DEFINE(HAVE_FCLOSE_D, 1)]) + +AC_MSG_TRY_COMPILE(for getpass() declaration, ftp_cv_HAVE_GETPASS_D, [ +#include <stdlib.h> +#include <unistd.h> ], [ char *(*X)() = getpass ], [ + AC_DEFINE(HAVE_GETPASS_D, 1)]) + +AC_MSG_TRY_COMPILE(for optarg declaration, ftp_cv_HAVE_OPTARG_D, [ +#include <stdlib.h> +#include <unistd.h> ], [ char *X = optarg ], [AC_DEFINE(HAVE_OPTARG_D, 1)]) + +AC_MSG_TRY_COMPILE(for optind declaration, ftp_cv_HAVE_OPTIND_D, [ +#include <stdlib.h> +#include <unistd.h> ], [ int X = optind ], [AC_DEFINE(HAVE_OPTIND_D, 1)]) + +AC_MSG_TRY_COMPILE(for pclose() declaration, ftp_cv_HAVE_PCLOSE_D, [ +#include <stdio.h> ], [ int (*X)() = pclose ], [AC_DEFINE(HAVE_PCLOSE_D, 1)]) + + +dnl Checks for library functions. +dnl +AC_REPLACE_FUNCS(err fgetln fseeko getaddrinfo getnameinfo inet_ntop inet_pton \ + mkstemp setprogname sl_init snprintf strdup strerror strlcat \ + strlcpy strptime strsep strunvis strvis timegm usleep) +AC_CHECK_FUNCS(gethostbyname2 getpassphrase getpgrp memmove poll select) +if test $ac_cv_func_getpgrp = yes; then + AC_FUNC_GETPGRP +fi +if test $ac_cv_lib_util_fparseln != yes; then + AC_REPLACE_FUNCS(fparseln) +fi + +LIBOBJS="$LIBOBJS glob.o" + +if test $ac_cv_func_strptime = yes; then + AC_MSG_TRY_COMPILE(for strptime() declaration, ftp_cv_HAVE_STRPTIME_D, [ + #include <time.h> ], [ char *X = strptime("", "", NULL) ], + [AC_DEFINE(HAVE_STRPTIME_D, 1)]) +fi + +if test $have_long_long = yes -a $ac_cv_sizeof_off_t -ge 8; then + +dnl We assume that if sprintf() supports %lld or %qd, +dnl then all of *printf() does. If not, disable long long +dnl support because we don't know how to display it. + + AC_MSG_CHECKING(*printf() support for %lld) + can_printf_longlong=no + AC_TRY_RUN([ + #include <stdio.h> + int main() { + char buf[100]; + sprintf(buf, "%lld", 4294967300LL); + return (strcmp(buf, "4294967300")); + } + ], [ + AC_MSG_RESULT(yes) + can_printf_longlong=yes + ], [ + AC_MSG_RESULT(no) + ], [ : ]) + + if test $can_printf_longlong != yes; then + AC_MSG_CHECKING(*printf() support for %qd) + AC_TRY_RUN([ + #include <stdio.h> + int main() { + char buf[100]; + sprintf(buf, "%qd", 4294967300LL); + return (strcmp(buf, "4294967300")); + } + ], [ + AC_MSG_RESULT(yes) + can_printf_longlong=yes + AC_DEFINE(HAVE_PRINTF_QD, 1) + ], [ + AC_MSG_RESULT(no) + ], [ : ]) + fi + + if test $can_printf_longlong = yes; then + AC_DEFINE(HAVE_QUAD_SUPPORT, 1) + AC_REPLACE_FUNCS(strtoll) + fi + +fi + + +if test $opt_editcomplete = yes; then + if test $have_libedit = yes; then + AC_MSG_TRY_COMPILE(for EL_RPROMPT in libedit, + ftp_cv_have_libedit, [ + #include <histedit.h> ], [ int X = EL_RPROMPT ], [:], + have_libedit=no ) + fi + + AC_MSG_CHECKING(for working libedit) + if test $have_libedit = no; then + AC_MSG_RESULT(no - using my own) + INCLUDES="-I\${srcdir}/../libedit $INCLUDES" + LDFLAGS="-L../libedit $LDFLAGS" + LIBS="-ledit $LIBS" + LIBEDIT=libedit.a + LIBDEPENDS="$LIBDEPENDS ../libedit/libedit.a" + else + AC_MSG_RESULT(yes) + fi +else + CFLAGS="-DNO_EDITCOMPLETE $CFLAGS" +fi + +if test $ac_cv_func_sl_init = yes; then + AC_MSG_TRY_COMPILE(if sl_add() returns int, ftp_cv_INT_SL_ADD, [ + #include <stringlist.h> ], [ int f = sl_add((StringList *)0, "foo") ], + [:] , [LIBOBJS="$LIBOBJS sl_init.o"]) +fi + + +have_rfc2553_netdb=no +if test $ac_cv_func_getaddrinfo = yes -a ! -n "$socks"; then + AC_MSG_TRY_COMPILE(for AI_NUMERICHOST, + ftp_cv_have_ai_numerichost, [ + #include <sys/types.h> + #include <sys/socket.h> + #include <netdb.h> ], + [ int X = AI_NUMERICHOST ], [ have_rfc2553_netdb=yes ]) +fi +AC_MSG_CHECKING(for working getaddrinfo()) +if test $have_rfc2553_netdb = yes; then + AC_DEFINE(HAVE_RFC2553_NETDB, 1) + AC_MSG_RESULT(yes) +else + if test $ac_cv_func_getaddrinfo = yes; then + LIBOBJS="$LIBOBJS getaddrinfo.o" + AC_MSG_RESULT(no - using local version) + else + AC_MSG_RESULT(using local version) + fi +fi + + +if test $ac_cv_header_vis_h = yes; then + AC_MSG_TRY_COMPILE(for VIS_WHITE in vis.h, + ftp_cv_have_vis_white, [ + #include <sys/types.h> + #include <vis.h> ], [ int X = VIS_WHITE ], [:], + ac_cv_header_vis_h=no ) +fi + + +if test -n "$LIBOBJS"; then + INCLUDES="$INCLUDES -I\${srcdir}/../libukem" + LDFLAGS="$LDFLAGS -L../libukem" + LIBS="$LIBS -lukem" + LIBUKEM=libukem.a + LIBDEPENDS="$LIBDEPENDS ../libukem/libukem.a" +fi + +dnl Create the Makefiles +dnl + +AC_SUBST(INCLUDES) +AC_SUBST(LIBEDIT) +AC_SUBST(LIBUKEM) +AC_SUBST(LIBDEPENDS) + +AC_OUTPUT(Makefile libedit/Makefile libedit/makelist libukem/Makefile \ + src/Makefile) diff --git a/contrib/tnftp/diffout b/contrib/tnftp/diffout new file mode 100644 index 0000000..932f748 --- /dev/null +++ b/contrib/tnftp/diffout @@ -0,0 +1,3500 @@ +diff -Nru src/CVS/Entries /home/spock/ftp/CVS/Entries +--- src/CVS/Entries Thu Jan 30 11:00:13 2003 ++++ /home/spock/ftp/CVS/Entries Thu Jun 12 02:02:10 2003 +@@ -1,16 +1,17 @@ +-/Makefile.in/1.1.1.1/Thu Jul 19 16:26:12 2001// +-/cmds.c/1.1.1.2/Sat Jun 15 09:40:32 2002// +-/cmdtab.c/1.1.1.2/Sat Jun 15 09:40:33 2002// +-/complete.c/1.1.1.1/Thu Jul 19 16:26:13 2001// +-/domacro.c/1.1.1.2/Sat Jun 15 09:40:33 2002// +-/extern.h/1.1.1.2/Sat Jun 15 09:40:33 2002// +-/fetch.c/1.1.1.3/Sat Jun 15 09:40:34 2002// +-/ftp.1/1.1.1.3/Sat Jun 15 09:40:35 2002// +-/ftp.c/1.1.1.3/Sat Jun 15 09:40:36 2002// +-/ftp.cat1/1.1.1.1/Sat Jun 15 09:40:31 2002// +-/ftp_var.h/1.1.1.3/Sat Jun 15 09:40:36 2002// +-/main.c/1.1.1.3/Sat Jun 15 09:40:36 2002// +-/ruserpass.c/1.1.1.2/Sat Jun 15 09:40:36 2002// +-/util.c/1.1.1.2/Sat Jun 15 09:40:37 2002// +-/version.h/1.1.1.2/Sat Jun 15 09:40:37 2002// ++/Makefile/1.26/Tue Jan 21 16:08:06 2003// ++/cmds.c/1.100/Sat Nov 30 03:10:55 2002// ++/cmdtab.c/1.40/Mon Jul 29 04:24:47 2002// ++/complete.c/1.38/Mon May 1 10:35:17 2000// ++/domacro.c/1.19/Fri Feb 1 05:04:43 2002// ++/extern.h/1.61/Tue Jan 21 16:08:07 2003// ++/fetch.c/1.141/Wed May 14 14:31:00 2003// ++/ftp.1/1.94/Wed May 14 14:31:00 2003// ++/ftp.c/1.120/Wed Jun 5 10:20:49 2002// ++/ftp_var.h/1.64/Tue Jan 21 16:08:07 2003// ++/main.c/1.84/Wed May 14 14:31:00 2003// ++/progressbar.c/1.3/Fri Feb 28 09:53:49 2003// ++/progressbar.h/1.3/Fri Feb 28 09:53:49 2003// ++/ruserpass.c/1.28/Wed Nov 15 00:11:04 2000// ++/util.c/1.111/Fri Feb 28 09:54:51 2003// ++/version.h/1.30/Fri Feb 28 09:54:20 2003// + D +diff -Nru src/CVS/Repository /home/spock/ftp/CVS/Repository +--- src/CVS/Repository Thu Jan 30 11:00:13 2003 ++++ /home/spock/ftp/CVS/Repository Thu Jun 12 02:02:10 2003 +@@ -1 +1 @@ +-src/contrib/lukemftp/src ++src/usr.bin/ftp +diff -Nru src/CVS/Root /home/spock/ftp/CVS/Root +--- src/CVS/Root Thu Jan 30 11:00:13 2003 ++++ /home/spock/ftp/CVS/Root Thu Jun 12 02:02:09 2003 +@@ -1 +1 @@ +-spock@current:/cvs/ncvs ++:pserver:anoncvs@anoncvs.netbsd.org:/cvsroot +diff -Nru src/Makefile /home/spock/ftp/Makefile +--- src/Makefile Wed Dec 31 19:00:00 1969 ++++ /home/spock/ftp/Makefile Thu Jun 12 02:02:10 2003 +@@ -0,0 +1,26 @@ ++# $NetBSD: Makefile,v 1.26 2003/01/21 16:08:06 jhawk Exp $ ++# from: @(#)Makefile 8.2 (Berkeley) 4/3/94 ++ ++PROG= ftp ++SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \ ++ progressbar.c ruserpass.c util.c ++ ++# Uncomment the following to provide defaults for gate-ftp operation ++# ++#CPPFLAGS+=-DGATE_SERVER=\"ftp-gw.host\" # -DGATE_PORT=21 ++ ++.if defined(SMALLPROG) ++CPPFLAGS+=-DNO_EDITCOMPLETE -DNO_ABOUT ++.else ++LDADD+= -ledit -ltermcap ++DPADD+= ${LIBEDIT} ${LIBTERMCAP} ++.endif ++ ++.if !defined(SMALLPROG) || defined(SMALLPROG_INET6) ++CPPFLAGS+= -DINET6 ++.endif ++ ++cmds.o fetch.o: version.h ++main.o: ftp_var.h ++ ++.include <bsd.prog.mk> +diff -Nru src/Makefile.in /home/spock/ftp/Makefile.in +--- src/Makefile.in Thu Jul 19 12:26:12 2001 ++++ /home/spock/ftp/Makefile.in Wed Dec 31 19:00:00 1969 +@@ -1,43 +0,0 @@ +-# +-# $Id: Makefile.in,v 1.8 2000/08/08 07:04:27 lukem Exp $ +-# +- +-srcdir = @srcdir@ +-VPATH = @srcdir@ +-SHELL = /bin/sh +- +-prefix = @prefix@ +-exec_prefix = @exec_prefix@ +-bindir = @bindir@ +-mandir = @mandir@ +-transform = @program_transform_name@ +- +-mandircat1 = ${mandir}/cat1 +- +-CC = @CC@ +-CFLAGS = -I${srcdir} -I${srcdir}/.. -I. -I.. @INCLUDES@ @CFLAGS@ +-LIBS = @LIBS@ +-LDFLAGS = @LDFLAGS@ +- +-INSTALL = @INSTALL@ +- +-PROG = ftp +-OBJS = cmds.o cmdtab.o complete.o domacro.o fetch.o ftp.o main.o \ +- ruserpass.o util.o +- +-all: ${PROG} +- +-install: all +- -mkdir -p ${bindir} +- ${INSTALL} -m 555 ${PROG} ${bindir}/`echo ${PROG}|sed '$(transform)'` +- -mkdir -p ${mandircat1} +- ${INSTALL} -m 444 ${srcdir}/${PROG}.cat1 ${mandircat1}/`echo ${PROG}|sed '$(transform)'`.1 +- +-${PROG}: ${OBJS} @LIBDEPENDS@ +- ${CC} ${CFLAGS} ${LDFLAGS} -o ${PROG} ${OBJS} ${LIBS} +- +-clean: +- rm -f core ${PROG} ${OBJS} +- +-distclean: clean +- rm -f Makefile +diff -Nru src/cmds.c /home/spock/ftp/cmds.c +--- src/cmds.c Sat Jun 15 05:40:32 2002 ++++ /home/spock/ftp/cmds.c Thu Jun 12 02:02:10 2003 +@@ -1,4 +1,4 @@ +-/* $NetBSD: cmds.c,v 1.98 2002/06/05 10:20:46 lukem Exp $ */ ++/* $NetBSD: cmds.c,v 1.100 2002/11/30 03:10:55 lukem Exp $ */ + + /*- + * Copyright (c) 1996-2002 The NetBSD Foundation, Inc. +@@ -102,11 +102,35 @@ + * SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94"; ++#else ++__RCSID("$NetBSD: cmds.c,v 1.100 2002/11/30 03:10:55 lukem Exp $"); ++#endif ++#endif /* not lint */ ++ + /* + * FTP User Program -- Command Routines. + */ +- +-#include "lukemftp.h" ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <sys/stat.h> ++#include <sys/wait.h> ++#include <arpa/ftp.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <glob.h> ++#include <limits.h> ++#include <netdb.h> ++#include <paths.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <time.h> ++#include <unistd.h> + + #include "ftp_var.h" + #include "version.h" +@@ -1008,7 +1032,7 @@ + gatemode = 0; + else { + if (argc == 3) +- gateport = strdup(argv[2]); ++ gateport = xstrdup(argv[2]); + (void)strlcpy(gsbuf, argv[1], sizeof(gsbuf)); + gateserver = gsbuf; + gatemode = 1; +diff -Nru src/cmdtab.c /home/spock/ftp/cmdtab.c +--- src/cmdtab.c Sat Jun 15 05:40:33 2002 ++++ /home/spock/ftp/cmdtab.c Thu Jun 12 02:02:10 2003 +@@ -1,4 +1,4 @@ +-/* $NetBSD: cmdtab.c,v 1.39 2000/11/15 00:10:59 lukem Exp $ */ ++/* $NetBSD: cmdtab.c,v 1.40 2002/07/29 04:24:47 lukem Exp $ */ + + /*- + * Copyright (c) 1996-2000 The NetBSD Foundation, Inc. +@@ -69,8 +69,16 @@ + * SUCH DAMAGE. + */ + +-#include "lukemftp.h" ++#include <sys/cdefs.h> ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94"; ++#else ++__RCSID("$NetBSD: cmdtab.c,v 1.40 2002/07/29 04:24:47 lukem Exp $"); ++#endif ++#endif /* not lint */ + ++#include <stdio.h> + #include "ftp_var.h" + + /* +@@ -123,7 +131,7 @@ + char ntranshelp[] = "set translation table for default file name mapping"; + char optshelp[] = "show or set options for remote commands"; + char pagehelp[] = "view a remote file through your pager"; +-char passivehelp[] = "enter passive transfer mode"; ++char passivehelp[] = "toggle use of passive transfer mode"; + char plshelp[] = "list contents of remote path through your pager"; + char pmlsdhelp[] = "list contents of remote directory in a machine " + "parsable form through your pager"; +diff -Nru src/complete.c /home/spock/ftp/complete.c +--- src/complete.c Thu Jul 19 12:26:13 2001 ++++ /home/spock/ftp/complete.c Thu Jun 12 02:02:10 2003 +@@ -36,11 +36,23 @@ + * POSSIBILITY OF SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> ++#ifndef lint ++__RCSID("$NetBSD: complete.c,v 1.38 2000/05/01 10:35:17 lukem Exp $"); ++#endif /* not lint */ ++ + /* + * FTP user program - command and file completion routines + */ + +-#include "lukemftp.h" ++#include <sys/stat.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <dirent.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> + + #include "ftp_var.h" + +diff -Nru src/domacro.c /home/spock/ftp/domacro.c +--- src/domacro.c Sat Jun 15 05:40:33 2002 ++++ /home/spock/ftp/domacro.c Thu Jun 12 02:02:10 2003 +@@ -33,7 +33,18 @@ + * SUCH DAMAGE. + */ + +-#include "lukemftp.h" ++#include <sys/cdefs.h> ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94"; ++#else ++__RCSID("$NetBSD: domacro.c,v 1.19 2002/02/01 05:04:43 itojun Exp $"); ++#endif ++#endif /* not lint */ ++ ++#include <ctype.h> ++#include <stdio.h> ++#include <string.h> + + #include "ftp_var.h" + +diff -Nru src/extern.h /home/spock/ftp/extern.h +--- src/extern.h Sat Jun 15 05:40:33 2002 ++++ /home/spock/ftp/extern.h Thu Jun 12 02:02:10 2003 +@@ -1,7 +1,7 @@ +-/* $NetBSD: extern.h,v 1.60 2000/10/11 14:46:03 is Exp $ */ ++/* $NetBSD: extern.h,v 1.61 2003/01/21 16:08:07 jhawk Exp $ */ + + /*- +- * Copyright (c) 1996-2000 The NetBSD Foundation, Inc. ++ * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation +@@ -110,7 +110,6 @@ + void abortxfer(int); + void account(int, char **); + void ai_unmapped(struct addrinfo *); +-void alarmtimer(int); + int another(int *, char ***, const char *); + int auto_fetch(int, char **); + int auto_put(int, char **, const char *); +@@ -123,7 +122,7 @@ + void cmdtimeout(int); + void cmdscanner(void); + int command(const char *, ...) +- ; ++ __attribute__((__format__(__printf__, 1, 2))); + #ifndef NO_EDITCOMPLETE + unsigned char complete(EditLine *, int); + void controlediting(void); +@@ -183,14 +182,11 @@ + void page(int, char **); + int parseport(const char *, int); + int parserate(int, char **, int); +-void progressmeter(int); + char *prompt(void); + void proxabort(int); + void proxtrans(const char *, const char *, const char *); + void psabort(int); +-void psummary(int); + void pswitch(int); +-void ptransfer(int); + void put(int, char **); + void pwd(int, char **); + void quit(int, char **); +@@ -263,5 +259,3 @@ + StringList *xsl_init(void); + void xsl_add(StringList *, char *); + char *xstrdup(const char *); +-sigfunc xsignal(int, sigfunc); +-sigfunc xsignal_restart(int, sigfunc, int); +diff -Nru src/fetch.c /home/spock/ftp/fetch.c +--- src/fetch.c Sun Feb 16 14:45:52 2003 ++++ /home/spock/ftp/fetch.c Thu Jun 12 02:02:11 2003 +@@ -1,7 +1,7 @@ +-/* $NetBSD: fetch.c,v 1.136 2002/06/05 10:20:48 lukem Exp $ */ ++/* $NetBSD: fetch.c,v 1.141 2003/05/14 14:31:00 wiz Exp $ */ + + /*- +- * Copyright (c) 1997-2002 The NetBSD Foundation, Inc. ++ * Copyright (c) 1997-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation +@@ -39,11 +39,36 @@ + * POSSIBILITY OF SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> ++#ifndef lint ++__RCSID("$NetBSD: fetch.c,v 1.141 2003/05/14 14:31:00 wiz Exp $"); ++#endif /* not lint */ ++ + /* + * FTP User Program -- Command line file retrieval + */ + +-#include "lukemftp.h" ++#include <sys/types.h> ++#include <sys/param.h> ++#include <sys/socket.h> ++#include <sys/stat.h> ++#include <sys/time.h> ++ ++#include <netinet/in.h> ++ ++#include <arpa/ftp.h> ++#include <arpa/inet.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <errno.h> ++#include <netdb.h> ++#include <fcntl.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <time.h> + + #include "ftp_var.h" + #include "version.h" +@@ -155,7 +180,7 @@ + *response = (char *)xmalloc(rlen); + (void)strlcpy(*response, scheme, rlen); + len = strlcat(*response, " ", rlen); +- base64_encode(clear, clen, *response + len); ++ base64_encode(clear, clen, (u_char *)*response + len); + memset(clear, 0, clen); + rval = 0; + +@@ -235,12 +260,12 @@ + * XXX: this is not totally RFC 1738 compliant; <path> will have the + * leading `/' unless it's an ftp:// URL, as this makes things easier + * for file:// and http:// URLs. ftp:// URLs have the `/' between the +- * host and the url-path removed, but any additional leading slashes +- * in the url-path are retained (because they imply that we should ++ * host and the URL-path removed, but any additional leading slashes ++ * in the URL-path are retained (because they imply that we should + * later do "CWD" with a null argument). + * + * Examples: +- * input url output path ++ * input URL output path + * --------- ----------- + * "ftp://host" NULL + * "http://host/" NULL +@@ -484,7 +509,8 @@ + rval = fetch_ftp(url); + goto cleanup_fetch_url; + } +- warnx("Invalid URL (no file after directory) `%s'", url); ++ warnx("no file after directory (you must specify an " ++ "output file) `%s'", url); + goto cleanup_fetch_url; + } else { + if (debug) +@@ -1372,7 +1398,7 @@ + dir ? dir : "<null>", file ? file : "<null>"); + + dirhasglob = filehasglob = 0; +- if (doglob && (urltype == CLASSIC_URL_T || urltype == FTP_URL_T)) { ++ if (doglob && urltype == CLASSIC_URL_T) { + if (! EMPTYSTRING(dir) && strpbrk(dir, "*?[]{}") != NULL) + dirhasglob = 1; + if (! EMPTYSTRING(file) && strpbrk(file, "*?[]{}") != NULL) +@@ -1741,7 +1767,7 @@ + } + } + if (debug) +- fprintf(ttyout, "auto_put: url `%s' argv[2] `%s'\n", ++ fprintf(ttyout, "auto_put: URL `%s' argv[2] `%s'\n", + path, uargv[2] ? uargv[2] : "<null>"); + + /* connect and cwd */ +diff -Nru src/ftp.1 /home/spock/ftp/ftp.1 +--- src/ftp.1 Sat Jun 15 05:40:35 2002 ++++ /home/spock/ftp/ftp.1 Thu Jun 12 02:02:11 2003 +@@ -1,6 +1,6 @@ +-.\" $NetBSD: ftp.1,v 1.83 2002/06/05 10:20:48 lukem Exp $ ++.\" $NetBSD: ftp.1,v 1.94 2003/05/14 14:31:00 wiz Exp $ + .\" +-.\" Copyright (c) 1996-2002 The NetBSD Foundation, Inc. ++.\" Copyright (c) 1996-2003 The NetBSD Foundation, Inc. + .\" All rights reserved. + .\" + .\" This code is derived from software contributed to The NetBSD Foundation +@@ -68,7 +68,7 @@ + .\" + .\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 + .\" +-.Dd May 18, 2002 ++.Dd January 20, 2003 + .Dt FTP 1 + .Os + .Sh NAME +@@ -76,7 +76,7 @@ + .Nd + Internet file transfer program + .Sh SYNOPSIS +-.Nm "" ++.Nm + .Op Fl 46AadefginpRtvV + .Bk -words + .Op Fl N Ar netrc +@@ -88,46 +88,81 @@ + .Op Fl P Ar port + .Ek + .Bk -words ++.Op Fl q Ar quittime ++.Ek ++.Bk -words + .Op Fl r Ar retry + .Ek + .Bk -words ++.\" [-T dir,max[,inc]] + .Oo +-.Fl T ++.Fl T Xo + .Sm off +-.Xo + .Ar dir , + .Ar max + .Op , Ar inc +-.Xc + .Sm on ++.Xc + .Oc + .Ek + .Bk -words ++.\" [[user@]host [port]] + .Oo +-[\fIuser\fR@]\fIhost\fR ++.Oo Ar user Ns Li \&@ Oc Ns Ar host + .Op Ar port + .Oc + .Ek + .Bk -words +-[\fIuser\fR@]\fIhost\fR:[\fIpath\fR][/] ++.\" [[user@]host:[path][/]] ++.Sm off ++.Oo ++.Op Ar user Li \&@ ++.Ar host Li \&: ++.Op Ar path ++.Op Li / ++.Oc ++.Sm on + .Ek + .Bk -words +-.Op file:///\fIpath\fR ++.\" [file:///path] ++.Sm off ++.Oo ++.Li file:/// Ar path ++.Oc ++.Sm on + .Ek + .Bk -words +-.Op ftp://[\fIuser\fR[:\fIpassword\fR]@]\fIhost\fR[:\fIport\fR]/\fIpath\fR[/] ++.\" [ftp://[user[:password]@]host[:port]/path[/]] ++.Sm off ++.Oo ++.Li ftp:// ++.Oo Ar user ++.Op Li \&: Ar password ++.Li \&@ Oc ++.Ar host Oo Li \&: Ar port Oc ++.Li / Ar path ++.Op Li / ++.Op Li ;type= Ar X ++.Oc ++.Sm on + .Ek + .Bk -words +-.Op http://[\fIuser\fR[:\fIpassword\fR]@]\fIhost\fR[:\fIport\fR]/\fIpath\fR ++.\" [http://[user[:password]@]host[:port]/path] ++.Sm off ++.Oo ++.Li http:// ++.Oo Ar user ++.Op Li \&: Ar password ++.Li \&@ Oc ++.Ar host Oo Li \&: Ar port Oc ++.Li / Ar path ++.Oc ++.Sm on + .Ek + .Op Ar \&.\&.\&. +-.Nm "" +-.Fl u Ar url +-.\".Ar ftp://[\fIuser\fR[:\fIpassword\fR]@]\fIhost\fR[:\fIport\fR]/\fIpath\fR[/[file]] +-.\"| +-.\".Ar [\fIuser\fR@]\fIhost\fR:[\fIpath\fR][/[\fIfile\fR]] ++.Nm + .Bk -words +-file ++.Fl u Ar URL Ar file + .Ek + .Op Ar \&.\&.\&. + .Sh DESCRIPTION +@@ -243,6 +278,10 @@ + Retry the connection attempt if it failed, pausing for + .Ar wait + seconds. ++.It Fl q Ar quittime ++Quit if the connection has stalled for ++.Ar quittime ++seconds. + .It Fl R + Restart all non-proxied auto-fetches. + .It Fl t +@@ -266,11 +305,11 @@ + Refer to + .Ic rate + for more information. +-.It Fl u Ar url file Op \&.\&.\&. ++.It Fl u Ar URL file Op \&.\&.\&. + Upload files on the command line to +-.Ar url ++.Ar URL + where +-.Ar url ++.Ar URL + is one of the ftp URL types as supported by auto-fetch + (with an optional target filename for single file uploads), and + .Ar file +@@ -869,7 +908,7 @@ + .Tn FTP + server at that port. + If the +-.Ic auto-login ++.Ic "set auto-login" + option is on (default), + .Nm + will also attempt to automatically log the user in to +@@ -882,10 +921,10 @@ + and display with the program specified by the + .Ic "set pager" + option. +-.It Ic passive Op Ic auto ++.It Ic passive Op Cm auto + Toggle passive mode (if no arguments are given). + If +-.Ic auto ++.Cm auto + is given, act as if + .Ev FTPMODE + is set to +@@ -896,14 +935,17 @@ + .Dv PASV + command for all data connections instead of a + .Dv PORT +-command. The ++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 ++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 ++server, who connects back to it. ++Passive mode is useful when using + .Nm + through a gateway router or host that controls the directionality of + traffic. +@@ -965,34 +1007,34 @@ + .Pp + When prompting is on, the following commands are available at a prompt: + .Bl -tag -width 2n -offset indent +-.It Ic a ++.It Cm a + Answer + .Sq yes + to the current file, and automatically answer + .Sq yes + to any remaining files for the current command. +-.It Ic n ++.It Cm n + Answer + .Sq no , + and do not transfer the file. +-.It Ic p ++.It Cm p + Answer + .Sq yes + to the current file, and turn off prompt mode + (as is + .Dq prompt off + had been given). +-.It Ic q ++.It Cm q + Terminate the current operation. +-.It Ic y ++.It Cm y + Answer + .Sq yes , + and transfer the file. +-.It Ic ? ++.It Cm ? + Display a help message. + .El + .Pp +-Any other reponse will answer ++Any other response will answer + .Sq yes + to the current file. + .It Ic proxy Ar ftp-command +@@ -1072,11 +1114,11 @@ + .Ar direction + may be one of: + .Bl -tag -width "all" -offset indent -compact +-.It Ic all ++.It Cm all + Both directions. +-.It Ic get ++.It Cm get + Incoming transfers. +-.It Ic put ++.It Cm put + Outgoing transfers. + .El + .Pp +@@ -1240,7 +1282,7 @@ + implementations which do ignore + .Dv PORT + commands but, incorrectly, indicate they've been accepted. +-.It Ic set Op Ar "option value" ++.It Ic set Op Ar option Ar value + Set + .Ar option + to +@@ -1252,25 +1294,25 @@ + are not given, display all of the options and their values. + The currently supported options are: + .Bl -tag -width "http_proxy" -offset indent +-.It anonpass ++.It Cm anonpass + Defaults to + .Ev $FTPANONPASS +-.It ftp_proxy ++.It Cm ftp_proxy + Defaults to + .Ev $ftp_proxy . +-.It http_proxy ++.It Cm http_proxy + Defaults to + .Ev $http_proxy . +-.It no_proxy ++.It Cm no_proxy + Defaults to + .Ev $no_proxy . +-.It pager ++.It Cm pager + Defaults to + .Ev $PAGER . +-.It prompt ++.It Cm prompt + Defaults to + .Ev $FTPPROMPT . +-.It rprompt ++.It Cm rprompt + Defaults to + .Ev $FTPRPROMPT . + .El +@@ -1415,13 +1457,14 @@ + interpretation of the argument. + Supported suffixes are: + .Bl -tag -width 3n -offset indent -compact +-.It b +-Causes no modification. (Optional) +-.It k ++.It Li b ++Causes no modification. ++(Optional) ++.It Li k + Kilo; multiply the argument by 1024 +-.It m ++.It Li m + Mega; multiply the argument by 1048576 +-.It g ++.It Li g + Giga; multiply the argument by 1073741824 + .El + .Pp +@@ -1447,7 +1490,15 @@ + .Pp + The following formats are valid syntax for an auto-fetch element: + .Bl -tag -width "FOO " +-.It [user@]host:[path][/] ++.\" [user@]host:[path][/] ++.It Xo ++.Sm off ++.Op Ar user Li \&@ ++.Ar host Li \&: ++.Op Ar path ++.Op Li / ++.Sm on ++.Xc + .Dq Classic + .Tn FTP + format. +@@ -1471,7 +1522,19 @@ + in the current directory. + Otherwise, the full remote name is used as the local name, + relative to the local root directory. +-.It ftp://[user[:password]@]host[:port]/path[/][;type=X] ++.\" ftp://[user[:password]@]host[:port]/path[/][;type=X] ++.It Xo ++.Sm off ++.Li ftp:// ++.Oo Ar user ++.Op Li \&: Ar password ++.Li \&@ Oc ++.Ar host Oo Li \&: Ar port Oc ++.Li / Ar path ++.Op Li / ++.Op Li ;type= Ar X ++.Sm on ++.Xc + An + .Tn FTP + URL, retrieved using the +@@ -1493,15 +1556,94 @@ + .Ar password + if supplied, otherwise prompt the user for one. + .Pp ++If a suffix of ++.Sq ;type=A ++or ++.Sq ;type=I ++is supplied, then the transfer type will take place as ++ascii or binary (respectively). ++The default transfer type is binary. ++.Pp + In order to be compliant with + .Cm RFC 1738 , + .Nm +-strips the leading +-.Sq / +-from ++interprets the ++.Ar path ++part of an ++.Dq ftp:// ++auto-fetch URL as follows: ++.Bl -bullet ++.It ++The ++.Sq Li / ++immediately after the ++.Ar host Ns Oo Li \&: Ns Ar port Oc ++is interpreted as a separator before the ++.Ar path , ++and not as part of the ++.Ar path ++itself. ++.It ++The ++.Ar path ++is interpreted as a ++.So Li / Sc Ns -separated ++list of name components. ++For all but the last such component, ++.Nm ++performs the equivalent of a ++.Ic cd ++command. ++For the last path component, ++.Nm ++performs the equivalent of a ++.Ic get ++command. ++.It ++Empty name components, ++which result from ++.Sq Li // ++within the ++.Ar path , ++or from an extra ++.Sq Li / ++at the beginning of the + .Ar path , +-resulting in a transfer relative from the default login directory of +-the user. ++will cause the equivalent of a ++.Ic cd ++command without a directory name. ++This is unlikely to be useful. ++.It ++Any ++.Sq Li \&% Ns Ar XX ++codes within the path components are decoded, with ++.Ar XX ++representing a character code in hexadecimal. ++This decoding takes place after the ++.Ar path ++has been split into components, ++but before each component is used in the equivalent of a ++.Ic cd ++or ++.Ic get ++command. ++Some often-used codes are ++.Sq Li \&%2F ++(which represents ++.Sq Li / ) ++and ++.Sq Li \&%7E ++(which represents ++.Sq Li ~ ) . ++.El ++.Pp ++The above interpretation has the following consequences: ++.Bl -bullet ++.It ++The path is interpreted relative to the ++default login directory of the specified user or of the ++.Sq anonymous ++user. + If the + .Pa / + directory is required, use a leading path of +@@ -1519,15 +1661,57 @@ + .Sq mypass , + use + .Dq ftp://myname:mypass@localhost/%2fetc/motd +-.Pp +-If a suffix of +-.Sq ;type=A +-or +-.Sq ;type=I +-is supplied, then the transfer type will take place as +-ascii or binary (respectively). +-The default transfer type is binary. +-.It http://[user[:password]@]host[:port]/path ++.It ++The exact ++.Ic cd ++and ++.Ic get ++commands can be controlled by careful choice of ++where to use ++.Sq / ++and where to use ++.Sq %2F ++(or ++.Sq %2f ) . ++For example, the following URLs correspond to the ++equivalents of the indicated commands: ++.Bl -tag -width "ftp://host/%2Fdir1%2Fdir2%2Ffile" ++.It ftp://host/dir1/dir2/file ++.Dq "cd dir1" , ++.Dq "cd dir2" , ++.Dq "get file" . ++.It ftp://host/%2Fdir1/dir2/file ++.Dq "cd /dir1" , ++.Dq "cd dir2" , ++.Dq "get file" . ++.It ftp://host/dir1%2Fdir2/file ++.Dq "cd dir1/dir2" , ++.Dq "get file" . ++.It ftp://host/%2Fdir1%2Fdir2/file ++.Dq "cd /dir1/dir2" , ++.Dq "get file" . ++.It ftp://host/dir1%2Fdir2%2Ffile ++.Dq "get dir1/dir2/file" . ++.It ftp://host/%2Fdir1%2Fdir2%2Ffile ++.Dq "get /dir1/dir2/file" . ++.El ++.It ++You must have appropriate access permission for each of the ++intermediate directories that is used in the equivalent of a ++.Ic cd ++command. ++.El ++.\" http://[user[:password]@]host[:port]/path ++.It Xo ++.Sm off ++.Li http:// ++.Oo Ar user ++.Op Li \&: Ar password ++.Li \&@ Oc ++.Ar host Oo Li \&: Ar port Oc ++.Li / Ar path ++.Sm on ++.Xc + An + .Tn HTTP + URL, retrieved using the +@@ -1540,16 +1724,22 @@ + proxy server. + If + .Tn HTTP +-authorisation is required to retrieve ++authorization is required to retrieve + .Ar path , + and + .Sq user + (and optionally + .Sq password ) + is in the URL, use them for the first attempt to authenticate. +-.It file:///path ++.\" file:///path ++.It Xo ++.Sm off ++.Li file:/// Ar path ++.Sm on ++.Xc + A local URL, copied from +-.Ar /path . ++.Pa / Ns Ar path ++on the local host. + .El + .Pp + Unless noted otherwise above, and +@@ -1736,7 +1926,7 @@ + .Nm + supports only the default values for the remaining + file transfer parameters: +-.Ic mode , ++.Ic mode , + .Ic form , + and + .Ic struct . +@@ -1841,6 +2031,14 @@ + .Ic init + is defined, it is automatically executed as the last step in the + auto-login process. ++For example, ++.Bd -literal -offset indent ++default ++macdef init ++epsv4 off ++.Ed ++.Pp ++followed by a blank line. + .El + .Sh COMMAND LINE EDITING + .Nm +@@ -1888,9 +2086,20 @@ + The following formatting sequences are replaced by the given + information: + .Bl -tag -width "%% " -offset indent +-.It %/ ++.It Li \&%/ + The current remote working directory. +-.It %c[[0]\fIn\fR], %.[[0]\fIn\fR] ++.\" %c[[0]n], %.[[0]n] ++.It Xo ++.Sm off ++.Li \&%c ++.Op Oo Li 0 Oc Ar n ++.Sm on ++.No , ++.Sm off ++.Li \&%. ++.Op Oo Li 0 Oc Ar n ++.Sm on ++.Xc + The trailing component of the current remote working directory, or + .Em n + trailing components if a digit +@@ -1902,21 +2111,28 @@ + .Sq 0 , + the number of skipped components precede the trailing component(s) in + the format +-.Dq /\fI\*[Lt]skipped\*[Gt]\fRtrailing ++.\" ``/<number>trailing'' ++.Do ++.Sm off ++.Li / Li \*[Lt] Va number Li \*[Gt] ++.Va trailing ++.Sm on ++.Dc + (for +-.Sq %c ) ++.Sq \&%c ) + or +-.Dq ...trailing ++.\" ``...trailing'' ++.Dq Li \&... Ns Va trailing + (for +-.Sq %. ) . +-.It %M ++.Sq \&%. ) . ++.It Li \&%M + The remote host name. +-.It %m ++.It Li \&%m + The remote host name, up to the first + .Sq \&. . +-.It %n ++.It Li \&%n + The remote user name. +-.It %% ++.It Li \&%% + A single + .Sq % . + .El +@@ -1934,15 +2150,15 @@ + Overrides the default operation mode. + Support values are: + .Bl -tag -width "passive" +-.It active ++.It Cm active + active mode + .Tn FTP + only +-.It auto ++.It Cm auto + automatic determination of passive or active (this is the default) +-.It gate ++.It Cm gate + gate-ftp mode +-.It passive ++.It Cm passive + passive mode + .Tn FTP + only +@@ -2028,6 +2244,21 @@ + Each entry may have an optional trailing ":port", which restricts + the matching to connections to that port. + .El ++.Sh EXTENDED PASSIVE MODE AND FIREWALLS ++Some firewall configurations do not allow ++.Nm ++to use extended passive mode. ++If you find that even a simple ++.Ic ls ++appears to hang after printing a message such as this: ++.Pp ++.Dl 229 Entering Extended Passive Mode (|||58551|) ++.Pp ++then you will need to disable extended passive mode with ++.Ic epsv4 off . ++See the above section ++.Sx The .netrc File ++for an example of how to make this automatic. + .Sh SEE ALSO + .Xr getservbyname 3 , + .Xr editrc 5 , +@@ -2061,7 +2292,9 @@ + were implemented in + .Nx 1.3 + and later releases +-by Luke Mewburn \*[Lt]lukem@netbsd.org\*[Gt]. ++by ++.An Luke Mewburn ++.Aq lukem@NetBSD.org . + .Pp + IPv6 support was added by the WIDE/KAME project + (but may not be present in all non-NetBSD versions of this program, depending +diff -Nru src/ftp.c /home/spock/ftp/ftp.c +--- src/ftp.c Sat Jun 15 05:40:36 2002 ++++ /home/spock/ftp/ftp.c Thu Jun 12 02:02:11 2003 +@@ -98,9 +98,40 @@ + * SUCH DAMAGE. + */ + +-#include "lukemftp.h" ++#include <sys/cdefs.h> ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; ++#else ++__RCSID("$NetBSD: ftp.c,v 1.120 2002/06/05 10:20:49 lukem Exp $"); ++#endif ++#endif /* not lint */ + ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <sys/socket.h> ++#include <sys/time.h> ++ ++#include <netinet/in.h> ++#include <netinet/in_systm.h> ++#include <netinet/ip.h> ++#include <arpa/inet.h> ++#include <arpa/ftp.h> + #include <arpa/telnet.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <errno.h> ++#include <netdb.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <time.h> ++#include <unistd.h> ++#include <stdarg.h> ++#ifndef USE_SELECT ++#include <poll.h> ++#endif + + #include "ftp_var.h" + +diff -Nru src/ftp.cat1 /home/spock/ftp/ftp.cat1 +--- src/ftp.cat1 Sat Jun 15 05:40:31 2002 ++++ /home/spock/ftp/ftp.cat1 Wed Dec 31 19:00:00 1969 +@@ -1,1055 +0,0 @@ +-FTP(1) NetBSD Reference Manual FTP(1) +- +-NNAAMMEE +- ffttpp - Internet file transfer program +- +-SSYYNNOOPPSSIISS +- ffttpp [--4466AAaaddeeffggiinnppRRttvvVV] [--NN _n_e_t_r_c] [--oo _o_u_t_p_u_t] [--PP _p_o_r_t] [--rr _r_e_t_r_y] [--TT +- _d_i_r,_m_a_x[,_i_n_c]] [[_u_s_e_r@]_h_o_s_t [_p_o_r_t]] [_u_s_e_r@]_h_o_s_t:[_p_a_t_h][/] +- [file:///_p_a_t_h] [ftp://[_u_s_e_r[:_p_a_s_s_w_o_r_d]@]_h_o_s_t[:_p_o_r_t]/_p_a_t_h[/]] +- [http://[_u_s_e_r[:_p_a_s_s_w_o_r_d]@]_h_o_s_t[:_p_o_r_t]/_p_a_t_h] [_._._.] +- ffttpp --uu _u_r_l file [_._._.] +- +-DDEESSCCRRIIPPTTIIOONN +- ffttpp is the user interface to the Internet standard File Transfer Proto- +- col. The program allows a user to transfer files to and from a remote +- network site. +- +- The last five arguments will fetch a file using the FTP or HTTP proto- +- cols, or by direct copying, into the current directory. This is ideal +- for scripts. Refer to _A_U_T_O_-_F_E_T_C_H_I_N_G _F_I_L_E_S below for more information. +- +- Options may be specified at the command line, or to the command inter- +- preter. +- +- --44 Forces ffttpp to only use IPv4 addresses. +- +- --66 Forces ffttpp to only use IPv6 addresses. +- +- --AA Force active mode ftp. By default, ffttpp will try to use passive +- mode ftp and fall back to active mode if passive is not support- +- ed by the server. This option causes ffttpp to always use an ac- +- tive connection. It is only useful for connecting to very old +- servers that do not implement passive mode properly. +- +- --aa Causes ffttpp to bypass normal login procedure, and use an anony- +- mous login instead. +- +- --dd Enables debugging. +- +- --ee Disables command line editing. This is useful for Emacs ange- +- ftp mode. +- +- --ff Forces a cache reload for transfers that go through the FTP or +- HTTP proxies. +- +- --gg Disables file name globbing. +- +- --ii Turns off interactive prompting during multiple file transfers. +- +- --nn Restrains ffttpp from attempting ``auto-login'' upon initial con- +- nection. If auto-login is enabled, ffttpp will check the _._n_e_t_r_c +- (see below) file in the user's home directory for an entry de- +- scribing an account on the remote machine. If no entry exists, +- ffttpp will prompt for the remote machine login name (default is +- the user identity on the local machine), and, if necessary, +- prompt for a password and an account with which to login. +- +- --NN _n_e_t_r_c +- Use _n_e_t_r_c instead of _~_/_._n_e_t_r_c. Refer to _T_H_E _._n_e_t_r_c _F_I_L_E for +- more information. +- +- --oo _o_u_t_p_u_t +- When auto-fetching files, save the contents in _o_u_t_p_u_t. _o_u_t_p_u_t +- is parsed according to the _F_I_L_E _N_A_M_I_N_G _C_O_N_V_E_N_T_I_O_N_S below. If +- _o_u_t_p_u_t is not `-' or doesn't start with `|', then only the first +- file specified will be retrieved into _o_u_t_p_u_t; all other files +- will be retrieved into the basename of their remote name. +- +- --pp Enable passive mode operation for use behind connection filter- +- ing firewalls. This option has been deprecated as ffttpp now tries +- to use passive mode by default, falling back to active mode if +- the server does not support passive connections. +- +- --PP _p_o_r_t Sets the port number to _p_o_r_t. +- +- --rr _w_a_i_t Retry the connection attempt if it failed, pausing for _w_a_i_t sec- +- onds. +- +- --RR Restart all non-proxied auto-fetches. +- +- --tt Enables packet tracing. +- +- --TT _d_i_r_e_c_t_i_o_n,_m_a_x_i_m_u_m[,_i_n_c_r_e_m_e_n_t] +- Set the maximum transfer rate for _d_i_r_e_c_t_i_o_n to _m_a_x_i_m_u_m +- bytes/second, and if specified, the increment to _i_n_c_r_e_m_e_n_t +- bytes/second. Refer to rraattee for more information. +- +- --uu _u_r_l _f_i_l_e [...] +- Upload files on the command line to _u_r_l where _u_r_l is one of the +- ftp URL types as supported by auto-fetch (with an optional tar- +- get filename for single file uploads), and _f_i_l_e is one or more +- local files to be uploaded. +- +- --vv Enable vveerrbboossee and pprrooggrreessss. This is the default if output is +- to a terminal (and in the case of pprrooggrreessss, ffttpp is the fore- +- ground process). Forces ffttpp to show all responses from the re- +- mote server, as well as report on data transfer statistics. +- +- --VV Disable vveerrbboossee and pprrooggrreessss, overriding the default of enabled +- when output is to a terminal. +- +- The client host with which ffttpp is to communicate may be specified on the +- command line. If this is done, ffttpp will immediately attempt to establish +- a connection to an FTP server on that host; otherwise, ffttpp will enter its +- command interpreter and await instructions from the user. When ffttpp is +- awaiting commands from the user the prompt `ftp>' is provided to the us- +- er. The following commands are recognized by ffttpp: +- +- !! [_c_o_m_m_a_n_d [_a_r_g_s]] +- 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. +- +- $$ _m_a_c_r_o_-_n_a_m_e [_a_r_g_s] +- Execute the macro _m_a_c_r_o_-_n_a_m_e that was defined with the mmaaccddeeff +- command. Arguments are passed to the macro unglobbed. +- +- aaccccoouunntt [_p_a_s_s_w_d] +- 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. +- +- aappppeenndd _l_o_c_a_l_-_f_i_l_e [_r_e_m_o_t_e_-_f_i_l_e] +- Append a local file to a file on the remote machine. If +- _r_e_m_o_t_e_-_f_i_l_e is left unspecified, the local file name is used +- in naming the remote file after being altered by any nnttrraannss +- or nnmmaapp setting. File transfer uses the current settings for +- ttyyppee, ffoorrmmaatt, mmooddee, and ssttrruuccttuurree. +- +- aasscciiii Set the file transfer ttyyppee to network ASCII. This is the de- +- fault type. +- +- bbeellll Arrange that a bell be sounded after each file transfer com- +- mand is completed. +- +- bbiinnaarryy Set the file transfer ttyyppee to support binary image transfer. +- +- bbyyee Terminate the FTP session with the remote server and exit +- ffttpp. An end of file will also terminate the session and ex- +- it. +- +- ccaassee Toggle remote computer file name case mapping during ggeett, +- mmggeett and mmppuutt commands. When ccaassee 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. +- +- ccdd _r_e_m_o_t_e_-_d_i_r_e_c_t_o_r_y +- Change the working directory on the remote machine to _r_e_m_o_t_e_- +- _d_i_r_e_c_t_o_r_y. +- +- ccdduupp Change the remote machine working directory to the parent of +- the current remote machine working directory. +- +- cchhmmoodd _m_o_d_e _r_e_m_o_t_e_-_f_i_l_e +- Change the permission modes of the file _r_e_m_o_t_e_-_f_i_l_e on the +- remote system to _m_o_d_e. +- +- cclloossee Terminate the FTP session with the remote server, and return +- to the command interpreter. Any defined macros are erased. +- +- ccrr Toggle carriage return stripping during ascii type file re- +- trieval. Records are denoted by a carriage return/linefeed +- sequence during ascii type file transfer. When ccrr is on (the +- default), carriage returns are stripped from this sequence to +- conform with the UNIX single linefeed record delimiter. +- Records on non-UNIX remote systems may contain single line- +- feeds; when an ascii type transfer is made, these linefeeds +- may be distinguished from a record delimiter only when ccrr is +- off. +- +- ddeebbuugg [_d_e_b_u_g_-_v_a_l_u_e] +- Toggle debugging mode. If an optional _d_e_b_u_g_-_v_a_l_u_e is speci- +- fied it is used to set the debugging level. When debugging +- is on, ffttpp prints each command sent to the remote machine, +- preceded by the string `-->' +- +- ddeelleettee _r_e_m_o_t_e_-_f_i_l_e +- Delete the file _r_e_m_o_t_e_-_f_i_l_e on the remote machine. +- +- ddiirr [_r_e_m_o_t_e_-_p_a_t_h [_l_o_c_a_l_-_f_i_l_e]] +- Print a listing of the contents of a directory on the remote +- machine. The listing includes any system-dependent informa- +- tion that the server chooses to include; for example, most +- UNIX systems will produce output from the command `ls -l'. +- If _r_e_m_o_t_e_-_p_a_t_h is left unspecified, the current working di- +- rectory is used. If interactive prompting is on, ffttpp will +- prompt the user to verify that the last argument is indeed +- the target local file for receiving ddiirr output. If no local +- file is specified, or if _l_o_c_a_l_-_f_i_l_e is `--', the output is +- sent to the terminal. +- +- ddiissccoonnnneecctt A synonym for cclloossee. +- +- eeddiitt Toggle command line editing, and context sensitive command +- and file completion. This is automatically enabled if input +- is from a terminal, and disabled otherwise. +- +- eeppssvv44 Toggle the use of the extended EPSV and EPRT commands on IPv4 +- connections; first try EPSV / EPRT, and then PASV / PORT. +- This is enabled by default. If an extended command fails +- then this option will be temporarily disabled for the dura- +- tion of the current connection, or until eeppssvv44 is executed +- again. +- +- eexxiitt A synonym for bbyyee. +- +- ffeeaattuurreess Display what features the remote server supports (using the +- FEAT command). +- +- ffggeett _l_o_c_a_l_f_i_l_e +- Retrieve the files listed in _l_o_c_a_l_f_i_l_e, which has one line +- per filename. +- +- ffoorrmm _f_o_r_m_a_t +- Set the file transfer ffoorrmm to _f_o_r_m_a_t. The default (and only +- supported) format is ``non-print''. +- +- ffttpp _h_o_s_t [_p_o_r_t] +- A synonym for ooppeenn. +- +- ggaattee [_h_o_s_t [_p_o_r_t]] +- Toggle gate-ftp mode, which used to connect through the TIS +- FWTK and Gauntlet ftp proxies. This will not be permitted if +- the gate-ftp server hasn't been set (either explicitly by the +- user, or from the FTPSERVER environment variable). If _h_o_s_t +- is given, then gate-ftp mode will be enabled, and the gate- +- ftp server will be set to _h_o_s_t. If _p_o_r_t is also given, that +- will be used as the port to connect to on the gate-ftp serv- +- er. +- +- ggeett _r_e_m_o_t_e_-_f_i_l_e [_l_o_c_a_l_-_f_i_l_e] +- Retrieve the _r_e_m_o_t_e_-_f_i_l_e 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 ccaassee, nnttrraannss, and nnmmaapp settings. The current +- settings for ttyyppee, ffoorrmm, mmooddee, and ssttrruuccttuurree are used while +- transferring the file. +- +- gglloobb Toggle filename expansion for mmddeelleettee, mmggeett, mmppuutt, and +- mmrreeggeett. If globbing is turned off with gglloobb, the file name +- arguments are taken literally and not expanded. Globbing for +- mmppuutt is done as in csh(1). For mmddeelleettee, mmggeett, and mmrreeggeett, +- each remote file name is expanded separately on the remote +- machine and the lists are not merged. Expansion of a direc- +- tory 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 `mls remote-files -' Note: mmggeett, mmppuutt and mmrreeggeett are +- not meant to transfer entire directory subtrees of files. +- That can be done by transferring a tar(1) archive of the sub- +- tree (in binary mode). +- +- hhaasshh [_s_i_z_e] +- Toggle hash-sign (``#'') printing for each data block trans- +- ferred. The size of a data block defaults to 1024 bytes. +- This can be changed by specifying _s_i_z_e in bytes. Enabling +- hhaasshh disables pprrooggrreessss. +- +- hheellpp [_c_o_m_m_a_n_d] +- Print an informative message about the meaning of _c_o_m_m_a_n_d. +- If no argument is given, ffttpp prints a list of the known com- +- mands. +- +- iiddllee [_s_e_c_o_n_d_s] +- Set the inactivity timer on the remote server to _s_e_c_o_n_d_s sec- +- onds. If _s_e_c_o_n_d_s is omitted, the current inactivity timer is +- printed. +- +- iimmaaggee A synonym for bbiinnaarryy. +- +- llccdd [_d_i_r_e_c_t_o_r_y] +- Change the working directory on the local machine. If no +- _d_i_r_e_c_t_o_r_y is specified, the user's home directory is used. +- +- lleessss _f_i_l_e A synonym for ppaaggee. +- +- llppaaggee _l_o_c_a_l_-_f_i_l_e +- Display _l_o_c_a_l_-_f_i_l_e with the program specified by the sseett +- ppaaggeerr option. +- +- llppwwdd Print the working directory on the local machine. +- +- llss [_r_e_m_o_t_e_-_p_a_t_h [_l_o_c_a_l_-_f_i_l_e]] +- A synonym for ddiirr. +- +- mmaaccddeeff _m_a_c_r_o_-_n_a_m_e +- Define a macro. Subsequent lines are stored as the macro +- _m_a_c_r_o_-_n_a_m_e; a null line (consecutive newline characters in a +- file or carriage returns from the terminal) terminates macro +- input mode. There is a limit of 16 macros and 4096 total +- characters in all defined macros. Macros remain defined un- +- til a cclloossee command is executed. The macro processor inter- +- prets `$' and `\' 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 `\' followed by any character is replaced by that charac- +- ter. Use the `\' to prevent special treatment of the `$'. +- +- mmddeelleettee [_r_e_m_o_t_e_-_f_i_l_e_s] +- Delete the _r_e_m_o_t_e_-_f_i_l_e_s on the remote machine. +- +- mmddiirr _r_e_m_o_t_e_-_f_i_l_e_s _l_o_c_a_l_-_f_i_l_e +- Like ddiirr, except multiple remote files may be specified. If +- interactive prompting is on, ffttpp will prompt the user to ver- +- ify that the last argument is indeed the target local file +- for receiving mmddiirr output. +- +- mmggeett _r_e_m_o_t_e_-_f_i_l_e_s +- Expand the _r_e_m_o_t_e_-_f_i_l_e_s on the remote machine and do a ggeett +- for each file name thus produced. See gglloobb for details on +- the filename expansion. Resulting file names will then be +- processed according to ccaassee, nnttrraannss, and nnmmaapp settings. +- Files are transferred into the local working directory, which +- can be changed with `lcd directory'; new local directories +- can be created with `! mkdir directory'. +- +- mmkkddiirr _d_i_r_e_c_t_o_r_y_-_n_a_m_e +- Make a directory on the remote machine. +- +- mmllss _r_e_m_o_t_e_-_f_i_l_e_s _l_o_c_a_l_-_f_i_l_e +- Like llss, except multiple remote files may be specified, and +- the _l_o_c_a_l_-_f_i_l_e must be specified. If interactive prompting +- is on, ffttpp will prompt the user to verify that the last argu- +- ment is indeed the target local file for receiving mmllss out- +- put. +- +- mmllssdd [_r_e_m_o_t_e_-_p_a_t_h] +- Display the contents of _r_e_m_o_t_e_-_p_a_t_h (which should default to +- the current directory if not given) in a machine-parsable +- form, using MLSD. The format of display can be changed with +- `remopts mlst ...'. +- +- mmllsstt [_r_e_m_o_t_e_-_p_a_t_h] +- Display the details about _r_e_m_o_t_e_-_p_a_t_h (which should default +- to the current directory if not given) in a machine-parsable +- form, using MLST. The format of display can be changed with +- `remopts mlst ...'. +- +- mmooddee _m_o_d_e_-_n_a_m_e +- Set the file transfer mmooddee to _m_o_d_e_-_n_a_m_e. The default (and +- only supported) mode is ``stream''. +- +- mmooddttiimmee _r_e_m_o_t_e_-_f_i_l_e +- Show the last modification time of the file on the remote ma- +- chine. +- +- mmoorree _f_i_l_e A synonym for ppaaggee. +- +- mmppuutt _l_o_c_a_l_-_f_i_l_e_s +- Expand wild cards in the list of local files given as argu- +- ments and do a ppuutt for each file in the resulting list. See +- gglloobb for details of filename expansion. Resulting file names +- will then be processed according to nnttrraannss and nnmmaapp settings. +- +- mmrreeggeett _r_e_m_o_t_e_-_f_i_l_e_s +- As per mmggeett, but performs a rreeggeett instead of ggeett. +- +- mmsseenndd _l_o_c_a_l_-_f_i_l_e_s +- A synonym for mmppuutt. +- +- nneewweerr _r_e_m_o_t_e_-_f_i_l_e [_l_o_c_a_l_-_f_i_l_e] +- 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 nneewweerr. Otherwise, this command is identical to +- _g_e_t. +- +- nnlliisstt [_r_e_m_o_t_e_-_p_a_t_h [_l_o_c_a_l_-_f_i_l_e]] +- A synonym for llss. +- +- nnmmaapp [_i_n_p_a_t_t_e_r_n _o_u_t_p_a_t_t_e_r_n] +- 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 +- mmppuutt commands and ppuutt commands issued without a specified re- +- mote target filename. If arguments are specified, local +- filenames are mapped during mmggeett commands and ggeett commands +- issued without a specified local target filename. This com- +- mand is useful when connecting to a non-UNIX remote computer +- with different file naming conventions or practices. The +- mapping follows the pattern set by _i_n_p_a_t_t_e_r_n and _o_u_t_p_a_t_t_e_r_n. +- [_I_n_p_a_t_t_e_r_n] is a template for incoming filenames (which may +- have already been processed according to the nnttrraannss and ccaassee +- settings). Variable templating is accomplished by including +- the sequences `$1', `$2', ..., `$9' in _i_n_p_a_t_t_e_r_n. Use `\' to +- prevent this special treatment of the `$' character. All +- other characters are treated literally, and are used to de- +- termine the nnmmaapp [_i_n_p_a_t_t_e_r_n] variable values. For example, +- given _i_n_p_a_t_t_e_r_n $1.$2 and the remote file name "mydata.data", +- $1 would have the value "mydata", and $2 would have the value +- "data". The _o_u_t_p_a_t_t_e_r_n determines the resulting mapped file- +- name. The sequences `$1', `$2', ...., `$9' are replaced by +- any value resulting from the _i_n_p_a_t_t_e_r_n template. The se- +- quence `$0' is replace by the original filename. Additional- +- ly, the sequence `[_s_e_q_1, _s_e_q_2]' is replaced by [_s_e_q_1] if _s_e_q_1 +- is not a null string; otherwise it is replaced by _s_e_q_2. For +- example, the command +- +- nmap $1.$2.$3 [$1,$2].[$2,file] +- +- would yield the output filename "myfile.data" for input file- +- names "myfile.data" and "myfile.data.old", "myfile.file" for +- the input filename "myfile", and "myfile.myfile" for the in- +- put filename ".myfile". Spaces may be included in +- _o_u_t_p_a_t_t_e_r_n, as in the example: `nmap $1 sed "s/ *$//" > $1' +- . Use the `\' character to prevent special treatment of the +- `$','[',']', and `,' characters. +- +- nnttrraannss [_i_n_c_h_a_r_s [_o_u_t_c_h_a_r_s]] +- Set or unset the filename character translation mechanism. +- If no arguments are specified, the filename character trans- +- lation mechanism is unset. If arguments are specified, char- +- acters in remote filenames are translated during mmppuutt com- +- mands and ppuutt commands issued without a specified remote tar- +- get filename. If arguments are specified, characters in lo- +- cal filenames are translated during mmggeett commands and ggeett +- commands issued without a specified local target filename. +- This command is useful when connecting to a non-UNIX remote +- computer with different file naming conventions or practices. +- Characters in a filename matching a character in _i_n_c_h_a_r_s are +- replaced with the corresponding character in _o_u_t_c_h_a_r_s. If +- the character's position in _i_n_c_h_a_r_s is longer than the length +- of _o_u_t_c_h_a_r_s, the character is deleted from the file name. +- +- ooppeenn _h_o_s_t [_p_o_r_t] +- Establish a connection to the specified _h_o_s_t FTP server. An +- optional port number may be supplied, in which case, ffttpp will +- attempt to contact an FTP server at that port. If the aauuttoo-- +- llooggiinn option is on (default), ffttpp will also attempt to auto- +- matically log the user in to the FTP server (see below). +- +- ppaaggee _f_i_l_e Retrieve ffiillee and display with the program specified by the +- sseett ppaaggeerr option. +- +- ppaassssiivvee [aauuttoo] +- Toggle passive mode (if no arguments are given). If aauuttoo is +- given, act as if FTPMODE is set to `auto'. If passive mode +- is turned on (default), ffttpp will send a PASV command for all +- data connections instead of a PORT command. The PASV command +- requests that the remote server open a port for the data con- +- nection 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 PORT command, the client lis- +- tens on a port and sends that address to the remote server, +- who connects back to it. Passive mode is useful when using +- ffttpp through a gateway router or host that controls the direc- +- tionality of traffic. (Note that though FTP servers are re- +- quired to support the PASV command by RFC 1123, some do not.) +- +- ppddiirr [_r_e_m_o_t_e_-_p_a_t_h] +- Perform ddiirr [_r_e_m_o_t_e_-_p_a_t_h], and display the result with the +- program specified by the sseett ppaaggeerr option. +- +- ppllss [_r_e_m_o_t_e_-_p_a_t_h] +- Perform llss [_r_e_m_o_t_e_-_p_a_t_h], and display the result with the +- program specified by the sseett ppaaggeerr option. +- +- ppmmllssdd [_r_e_m_o_t_e_-_p_a_t_h] +- Perform mmllssdd [_r_e_m_o_t_e_-_p_a_t_h], and display the result with the +- program specified by the sseett ppaaggeerr option. +- +- pprreesseerrvvee Toggle preservation of modification times on retrieved files. +- +- pprrooggrreessss Toggle display of transfer progress bar. The progress bar +- will be disabled for a transfer that has _l_o_c_a_l_-_f_i_l_e as `--' or +- a command that starts with `|'. Refer to _F_I_L_E _N_A_M_I_N_G +- _C_O_N_V_E_N_T_I_O_N_S for more information. Enabling pprrooggrreessss disables +- hhaasshh. +- +- pprroommpptt Toggle interactive prompting. Interactive prompting occurs +- during multiple file transfers to allow the user to selec- +- tively retrieve or store files. If prompting is turned off +- (default is on), any mmggeett or mmppuutt will transfer all files, +- and any mmddeelleettee will delete all files. +- +- When prompting is on, the following commands are available at +- a prompt: +- +- aa Answer `yes' to the current file, and automatically +- answer `yes' to any remaining files for the current +- command. +- +- nn Answer `no', and do not transfer the file. +- +- pp Answer `yes' to the current file, and turn off +- prompt mode (as is ``prompt off'' had been given). +- +- qq Terminate the current operation. +- +- yy Answer `yes', and transfer the file. +- +- ?? Display a help message. +- +- Any other reponse will answer `yes' to the current file. +- +- pprrooxxyy _f_t_p_-_c_o_m_m_a_n_d +- 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 pprrooxxyy command should be an ooppeenn, to establish the sec- +- ondary control connection. Enter the command "proxy ?" to +- see other FTP commands executable on the secondary connec- +- tion. The following commands behave differently when pref- +- aced by pprrooxxyy: ooppeenn will not define new macros during the au- +- to-login process, cclloossee will not erase existing macro defini- +- tions, ggeett and mmggeett transfer files from the host on the pri- +- mary control connection to the host on the secondary control +- connection, and ppuutt, mmppuutt, and aappppeenndd transfer files from the +- host on the secondary control connection to the host on the +- primary control connection. Third party file transfers de- +- pend upon support of the FTP protocol PASV command by the +- server on the secondary control connection. +- +- ppuutt _l_o_c_a_l_-_f_i_l_e [_r_e_m_o_t_e_-_f_i_l_e] +- Store a local file on the remote machine. If _r_e_m_o_t_e_-_f_i_l_e is +- left unspecified, the local file name is used after process- +- ing according to any nnttrraannss or nnmmaapp settings in naming the +- remote file. File transfer uses the current settings for +- ttyyppee, ffoorrmmaatt, mmooddee, and ssttrruuccttuurree. +- +- ppwwdd Print the name of the current working directory on the remote +- machine. +- +- qquuiitt A synonym for bbyyee. +- +- qquuoottee _a_r_g_1 _a_r_g_2 _._._. +- The arguments specified are sent, verbatim, to the remote FTP +- server. +- +- rraattee _d_i_r_e_c_t_i_o_n [_m_a_x_i_m_u_m [_i_n_c_r_e_m_e_n_t]] +- Throttle the maximum transfer rate to _m_a_x_i_m_u_m bytes/second. +- If _m_a_x_i_m_u_m is 0, disable the throttle. +- +- _d_i_r_e_c_t_i_o_n may be one of: +- aallll Both directions. +- ggeett Incoming transfers. +- ppuutt Outgoing transfers. +- +- _m_a_x_i_m_u_m can by modified on the fly by _i_n_c_r_e_m_e_n_t bytes (de- +- fault: 1024) each time a given signal is received: +- +- SIGUSR1 Increment _m_a_x_i_m_u_m by _i_n_c_r_e_m_e_n_t bytes. +- +- SIGUSR2 Decrement _m_a_x_i_m_u_m by _i_n_c_r_e_m_e_n_t bytes. The re- +- sult must be a positive number. +- +- If _m_a_x_i_m_u_m is not supplied, the current throttle rates are +- displayed. +- +- Note: rraattee is not yet implemented for ascii mode transfers. +- +- rrccvvbbuuff _s_i_z_e +- Set the size of the socket receive buffer to _s_i_z_e. +- +- rreeccvv _r_e_m_o_t_e_-_f_i_l_e [_l_o_c_a_l_-_f_i_l_e] +- A synonym for ggeett. +- +- rreeggeett _r_e_m_o_t_e_-_f_i_l_e [_l_o_c_a_l_-_f_i_l_e] +- rreeggeett acts like ggeett, except that if _l_o_c_a_l_-_f_i_l_e exists and is +- smaller than _r_e_m_o_t_e_-_f_i_l_e, _l_o_c_a_l_-_f_i_l_e is presumed to be a par- +- tially transferred copy of _r_e_m_o_t_e_-_f_i_l_e 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. +- +- rreemmooppttss _c_o_m_m_a_n_d [_c_o_m_m_a_n_d_-_o_p_t_i_o_n_s] +- Set options on the remote FTP server for _c_o_m_m_a_n_d to _c_o_m_m_a_n_d_- +- _o_p_t_i_o_n_s (whose absence is handled on a command-specific ba- +- sis). Remote FTP commands known to support options include: +- `MLST' (used for MLSD and MLST). +- +- rreennaammee [_f_r_o_m [_t_o]] +- Rename the file _f_r_o_m on the remote machine, to the file _t_o. +- +- rreesseett Clear reply queue. This command re-synchronizes command/re- +- ply sequencing with the remote FTP server. Resynchronization +- may be necessary following a violation of the FTP protocol by +- the remote server. +- +- rreessttaarrtt _m_a_r_k_e_r +- Restart the immediately following ggeett or ppuutt at the indicated +- _m_a_r_k_e_r. On UNIX systems, marker is usually a byte offset in- +- to the file. +- +- rrhheellpp [_c_o_m_m_a_n_d_-_n_a_m_e] +- Request help from the remote FTP server. If a _c_o_m_m_a_n_d_-_n_a_m_e +- is specified it is supplied to the server as well. +- +- rrmmddiirr _d_i_r_e_c_t_o_r_y_-_n_a_m_e +- Delete a directory on the remote machine. +- +- rrssttaattuuss [_r_e_m_o_t_e_-_f_i_l_e] +- With no arguments, show status of remote machine. If _r_e_m_o_t_e_- +- _f_i_l_e is specified, show status of _r_e_m_o_t_e_-_f_i_l_e on remote ma- +- chine. +- +- rruunniiqquuee Toggle storing of files on the local system with unique file- +- names. If a file already exists with a name equal to the +- target local filename for a ggeett or mmggeett 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 rruunniiqquuee will not +- affect local files generated from a shell command (see be- +- low). The default value is off. +- +- sseenndd _l_o_c_a_l_-_f_i_l_e [_r_e_m_o_t_e_-_f_i_l_e] +- A synonym for ppuutt. +- +- sseennddppoorrtt Toggle the use of PORT commands. By default, ffttpp will at- +- tempt to use a PORT command when establishing a connection +- for each data transfer. The use of PORT commands can prevent +- delays when performing multiple file transfers. If the PORT +- command fails, ffttpp will use the default data port. When the +- use of PORT commands is disabled, no attempt will be made to +- use PORT commands for each data transfer. This is useful for +- certain FTP implementations which do ignore PORT commands +- but, incorrectly, indicate they've been accepted. +- +- sseett [_o_p_t_i_o_n _v_a_l_u_e] +- Set _o_p_t_i_o_n to _v_a_l_u_e. If _o_p_t_i_o_n and _v_a_l_u_e are not given, dis- +- play all of the options and their values. The currently sup- +- ported options are: +- +- anonpass Defaults to $FTPANONPASS +- +- ftp_proxy Defaults to $ftp_proxy. +- +- http_proxy Defaults to $http_proxy. +- +- no_proxy Defaults to $no_proxy. +- +- pager Defaults to $PAGER. +- +- prompt Defaults to $FTPPROMPT. +- +- rprompt Defaults to $FTPRPROMPT. +- +- ssiittee _a_r_g_1 _a_r_g_2 _._._. +- The arguments specified are sent, verbatim, to the remote FTP +- server as a SITE command. +- +- ssiizzee _r_e_m_o_t_e_-_f_i_l_e +- Return size of _r_e_m_o_t_e_-_f_i_l_e on remote machine. +- +- ssnnddbbuuff _s_i_z_e +- Set the size of the socket send buffer to _s_i_z_e. +- +- ssttaattuuss Show the current status of ffttpp. +- +- ssttrruucctt _s_t_r_u_c_t_-_n_a_m_e +- Set the file transfer _s_t_r_u_c_t_u_r_e to _s_t_r_u_c_t_-_n_a_m_e. The default +- (and only supported) structure is ``file''. +- +- ssuunniiqquuee Toggle storing of files on remote machine under unique file +- names. The remote FTP server must support FTP protocol STOU +- command for successful completion. The remote server will +- report unique name. Default value is off. +- +- ssyysstteemm Show the type of operating system running on the remote ma- +- chine. +- +- tteenneexx Set the file transfer type to that needed to talk to TENEX +- machines. +- +- tthhrroottttllee A synonym for rraattee. +- +- ttrraaccee Toggle packet tracing. +- +- ttyyppee [_t_y_p_e_-_n_a_m_e] +- Set the file transfer ttyyppee to _t_y_p_e_-_n_a_m_e. If no type is spec- +- ified, the current type is printed. The default type is net- +- work ASCII. +- +- uummaasskk [_n_e_w_m_a_s_k] +- Set the default umask on the remote server to _n_e_w_m_a_s_k. If +- _n_e_w_m_a_s_k is omitted, the current umask is printed. +- +- uunnsseett _o_p_t_i_o_n +- Unset _o_p_t_i_o_n. Refer to sseett for more information. +- +- uussaaggee _c_o_m_m_a_n_d +- Print the usage message for _c_o_m_m_a_n_d. +- +- uusseerr _u_s_e_r_-_n_a_m_e [_p_a_s_s_w_o_r_d [_a_c_c_o_u_n_t]] +- Identify yourself to the remote FTP server. If the _p_a_s_s_w_o_r_d +- is not specified and the server requires it, ffttpp will prompt +- the user for it (after disabling local echo). If an _a_c_c_o_u_n_t +- field is not specified, and the FTP server requires it, the +- user will be prompted for it. If an _a_c_c_o_u_n_t field is speci- +- fied, 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 ffttpp is invoked +- with ``auto-login'' disabled, this process is done automati- +- cally on initial connection to the FTP server. +- +- vveerrbboossee Toggle verbose mode. In verbose mode, all responses from the +- FTP server are displayed to the user. In addition, if ver- +- bose is on, when a file transfer completes, statistics re- +- garding the efficiency of the transfer are reported. By de- +- fault, verbose is on. +- +- xxffeerrbbuuff _s_i_z_e +- Set the size of the socket send and receive buffers to _s_i_z_e. +- +- ?? [_c_o_m_m_a_n_d] +- A synonym for hheellpp. +- +- Command arguments which have embedded spaces may be quoted with quote `"' +- marks. +- +- Commands which toggle settings can take an explicit oonn or ooffff argument to +- force the setting appropriately. +- +- Commands which take a byte count as an argument (e.g., hhaasshh, rraattee, and +- xxffeerrbbuuff) support an optional suffix on the argument which changes the in- +- terpretation of the argument. Supported suffixes are: +- b Causes no modification. (Optional) +- k Kilo; multiply the argument by 1024 +- m Mega; multiply the argument by 1048576 +- g Giga; multiply the argument by 1073741824 +- +- If ffttpp receives a SIGINFO (see the ``status'' argument of stty(1)) or +- SIGQUIT signal whilst a transfer is in progress, the current transfer +- rate statistics will be written to the standard error output, in the same +- format as the standard completion message. +- +-AAUUTTOO--FFEETTCCHHIINNGG FFIILLEESS +- In addition to standard commands, this version of ffttpp supports an auto- +- fetch feature. To enable auto-fetch, simply pass the list of host- +- names/files on the command line. +- +- The following formats are valid syntax for an auto-fetch element: +- +- [user@]host:[path][/] +- ``Classic'' FTP format. +- +- If _p_a_t_h contains a glob character and globbing is enabled, (see +- gglloobb), then the equivalent of `mget path' is performed. +- +- If the directory component of _p_a_t_h contains no globbing characters, +- it is stored locally with the name basename (see basename(1)) of +- ppaatthh, in the current directory. Otherwise, the full remote name is +- used as the local name, relative to the local root directory. +- +- ftp://[user[:password]@]host[:port]/path[/][;type=X] +- An FTP URL, retrieved using the FTP protocol if sseett ffttpp__pprrooxxyy isn't +- defined. Otherwise, transfer the URL using HTTP via the proxy de- +- fined in sseett ffttpp__pprrooxxyy. If sseett ffttpp__pprrooxxyy isn't defined and _u_s_e_r is +- given, login as _u_s_e_r. In this case, use _p_a_s_s_w_o_r_d if supplied, oth- +- erwise prompt the user for one. +- +- In order to be compliant with RRFFCC 11773388, ffttpp strips the leading `/' +- from _p_a_t_h, resulting in a transfer relative from the default login +- directory of the user. If the _/ directory is required, use a lead- +- ing path of ``%2F''. If a user's home directory is required (and +- the remote server supports the syntax), use a leading path of +- ``%7Euser/''. For example, to retrieve _/_e_t_c_/_m_o_t_d from `localhost' +- as the user `myname' with the password `mypass', use +- ``ftp://myname:mypass@localhost/%2fetc/motd'' +- +- If a suffix of `;type=A' or `;type=I' is supplied, then the trans- +- fer type will take place as ascii or binary (respectively). The +- default transfer type is binary. +- +- http://[user[:password]@]host[:port]/path +- An HTTP URL, retrieved using the HTTP protocol. If sseett hhttttpp__pprrooxxyy +- is defined, it is used as a URL to an HTTP proxy server. If HTTP +- authorisation is required to retrieve _p_a_t_h, and `user' (and option- +- ally `password') is in the URL, use them for the first attempt to +- authenticate. +- +- file:///path +- A local URL, copied from _/_p_a_t_h. +- +- Unless noted otherwise above, and --oo _o_u_t_p_u_t is not given, the file is +- stored in the current directory as the basename(1) of _p_a_t_h. +- +- If a classic format or an FTP URL format has a trailing `/' or an empty +- _p_a_t_h component, then ffttpp will connect to the site and ccdd to the directory +- given as the path, and leave the user in interactive mode ready for fur- +- ther input. This will not work if sseett ffttpp__pprrooxxyy is being used. +- +- Direct HTTP transfers use HTTP 1.1. Proxied FTP and HTTP transfers use +- HTTP 1.0. +- +- If --RR is given, all auto-fetches that don't go via the FTP or HTTP prox- +- ies will be restarted. For FTP, this is implemented by using rreeggeett in- +- stead of ggeett. For HTTP, this is implemented by using the `Range: bytes=' +- HTTP/1.1 directive. +- +- If WWW or proxy WWW authentication is required, you will be prompted to +- enter a username and password to authenticate with. +- +- When specifying IPv6 numeric addresses in a URL, you need to surround the +- address in square brackets. E.g.: ``ftp://[::1]:21/''. This is because +- colons are used in IPv6 numeric address as well as being the separator +- for the port number. +- +-AABBOORRTTIINNGG AA FFIILLEE TTRRAANNSSFFEERR +- 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 an FTP protocol 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 ABOR +- processing. If the remote server does not support the ABOR command, the +- prompt will not appear until the remote server has completed sending the +- requested file. +- +- If the terminal interrupt key sequence is used whilst ffttpp is awaiting a +- reply from the remote server for the ABOR processing, then the connection +- will be closed. This is different from the traditional behaviour (which +- ignores the terminal interrupt during this phase), but is considered more +- useful. +- +-FFIILLEE NNAAMMIINNGG CCOONNVVEENNTTIIOONNSS +- Files specified as arguments to ffttpp commands are processed according to +- the following rules. +- +- 1. If the file name `--' is specified, the _s_t_d_i_n (for reading) or _s_t_d_o_u_t +- (for writing) is used. +- +- 2. If the first character of the file name is `|', the remainder of the +- argument is interpreted as a shell command. ffttpp then forks a shell, +- using popen(3) with the argument supplied, and reads (writes) from +- the stdout (stdin). If the shell command includes spaces, the argu- +- ment must be quoted; e.g. ``"| ls -lt"''. A particularly useful +- example of this mechanism is: ``dir "" |more''. +- +- 3. Failing the above checks, if ``globbing'' is enabled, local file +- names are expanded according to the rules used in the csh(1); c.f. +- the gglloobb command. If the ffttpp command expects a single local file +- (e.g. ppuutt), only the first filename generated by the "globbing" op- +- eration is used. +- +- 4. For mmggeett commands and ggeett commands with unspecified local file +- names, the local filename is the remote filename, which may be al- +- tered by a ccaassee, nnttrraannss, or nnmmaapp setting. The resulting filename +- may then be altered if rruunniiqquuee is on. +- +- 5. For mmppuutt commands and ppuutt commands with unspecified remote file +- names, the remote filename is the local filename, which may be al- +- tered by a nnttrraannss or nnmmaapp setting. The resulting filename may then +- be altered by the remote server if ssuunniiqquuee is on. +- +-FFIILLEE TTRRAANNSSFFEERR PPAARRAAMMEETTEERRSS +- The FTP specification specifies many parameters which may affect a file +- transfer. The ttyyppee may be one of ``ascii'', ``image'' (binary), +- ``ebcdic'', and ``local byte size'' (for PDP-10's and PDP-20's mostly). +- ffttpp supports the ascii and image types of file transfer, plus local byte +- size 8 for tteenneexx mode transfers. +- +- ffttpp supports only the default values for the remaining file transfer pa- +- rameters: mmooddee, ffoorrmm, and ssttrruucctt. +- +-TTHHEE ..nneettrrcc FFIILLEE +- The _._n_e_t_r_c file contains login and initialization information used by the +- auto-login process. It resides in the user's home directory, unless +- overridden with the --NN _n_e_t_r_c option, or specified in the NETRC environ- +- ment variable. The following tokens are recognized; they may be separat- +- ed by spaces, tabs, or new-lines: +- +- mmaacchhiinnee _n_a_m_e +- Identify a remote machine _n_a_m_e. The auto-login process search- +- es the _._n_e_t_r_c file for a mmaacchhiinnee token that matches the remote +- machine specified on the ffttpp command line or as an ooppeenn command +- argument. Once a match is made, the subsequent _._n_e_t_r_c tokens +- are processed, stopping when the end of file is reached or an- +- other mmaacchhiinnee or a ddeeffaauulltt token is encountered. +- +- ddeeffaauulltt This is the same as mmaacchhiinnee _n_a_m_e except that ddeeffaauulltt matches +- any name. There can be only one ddeeffaauulltt token, and it must be +- after all mmaacchhiinnee tokens. This is normally used as: +- +- default login anonymous password user@site +- +- thereby giving the user an automatic anonymous FTP login to ma- +- chines not specified in _._n_e_t_r_c. This can be overridden by us- +- ing the --nn flag to disable auto-login. +- +- llooggiinn _n_a_m_e +- Identify a user on the remote machine. If this token is pre- +- sent, the auto-login process will initiate a login using the +- specified _n_a_m_e. +- +- ppaasssswwoorrdd _s_t_r_i_n_g +- 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 _._n_e_t_r_c file for any user other +- than _a_n_o_n_y_m_o_u_s, ffttpp will abort the auto-login process if the +- _._n_e_t_r_c is readable by anyone besides the user. +- +- aaccccoouunntt _s_t_r_i_n_g +- Supply an additional account password. If this token is pre- +- sent, 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 ACCT command if it +- does not. +- +- mmaaccddeeff _n_a_m_e +- Define a macro. This token functions like the ffttpp mmaaccddeeff com- +- mand functions. A macro is defined with the specified name; +- its contents begin with the next _._n_e_t_r_c line and continue until +- a blank line (consecutive new-line characters) is encountered. +- If a macro named iinniitt is defined, it is automatically executed +- as the last step in the auto-login process. +- +-CCOOMMMMAANNDD LLIINNEE EEDDIITTIINNGG +- ffttpp supports interactive command line editing, via the editline(3) li- +- brary. It is enabled with the eeddiitt command, and is enabled by default if +- input is from a tty. Previous lines can be recalled and edited with the +- arrow keys, and other GNU Emacs-style editing keys may be used as well. +- +- The editline(3) library is configured with a _._e_d_i_t_r_c file - refer to +- editrc(5) for more information. +- +- An extra key binding is available to ffttpp to provide context sensitive +- command and filename completion (including remote file completion). To +- use this, bind a key to the editline(3) command ffttpp--ccoommpplleettee. By de- +- fault, this is bound to the TAB key. +- +-CCOOMMMMAANNDD LLIINNEE PPRROOMMPPTT +- By default, ffttpp displays a command line prompt of ``ftp>'' to the user. +- This can be changed with the sseett pprroommpptt command. +- +- A prompt can be displayed on the right side of the screen (after the com- +- mand input) with the sseett rrpprroommpptt command. +- +- The following formatting sequences are replaced by the given information: +- +- %/ The current remote working directory. +- +- %c[[0]_n], %.[[0]_n] +- The trailing component of the current remote working directo- +- ry, or _n trailing components if a digit _n is given. If _n be- +- gins with `0', the number of skipped components precede the +- trailing component(s) in the format ``/_<_s_k_i_p_p_e_d_>trailing'' +- (for `%c') or ``...trailing'' (for `%.'). +- +- %M The remote host name. +- +- %m The remote host name, up to the first `.'. +- +- %n The remote user name. +- +- %% A single `%'. +- +-EENNVVIIRROONNMMEENNTT +- ffttpp uses the following environment variables. +- +- FTPANONPASS Password to send in an anonymous FTP transfer. Defaults +- to ```whoami`@''. +- +- FTPMODE Overrides the default operation mode. Support values are: +- +- active active mode FTP only +- +- auto automatic determination of passive or active +- (this is the default) +- +- gate gate-ftp mode +- +- passive passive mode FTP only +- +- FTPPROMPT Command-line prompt to use. Defaults to ``ftp>''. Refer +- to _C_O_M_M_A_N_D _L_I_N_E _P_R_O_M_P_T for more information. +- +- FTPRPROMPT Command-line right side prompt to use. Defaults to ``''. +- Refer to _C_O_M_M_A_N_D _L_I_N_E _P_R_O_M_P_T for more information. +- +- FTPSERVER Host to use as gate-ftp server when ggaattee is enabled. +- +- FTPSERVERPORT Port to use when connecting to gate-ftp server when ggaattee +- is enabled. Default is port returned by a ggeettsseerrvvbbyynnaammee() +- lookup of ``ftpgate/tcp''. +- +- HOME For default location of a _._n_e_t_r_c file, if one exists. +- +- NETRC An alternate location of the _._n_e_t_r_c file. +- +- PAGER Used by various commands to display files. Defaults to +- more(1) if empty or not set. +- +- SHELL For default shell. +- +- ftp_proxy URL of FTP proxy to use when making FTP URL requests (if +- not defined, use the standard FTP protocol). +- +- _N_O_T_E: this is not used for interactive sessions, only for +- command-line fetches. +- +- http_proxy URL of HTTP proxy to use when making HTTP URL requests. +- If proxy authentication is required and there is a user- +- name and password in this URL, they will automatically be +- used in the first attempt to authenticate to the proxy. +- +- Note that the use of a username and password in ftp_proxy +- and http_proxy may be incompatible with other programs +- that use it (such as lynx(1)). +- +- _N_O_T_E: this is not used for interactive sessions, only for +- command-line fetches. +- +- no_proxy A space or comma separated list of hosts (or domains) for +- which proxying is not to be used. Each entry may have an +- optional trailing ":port", which restricts the matching to +- connections to that port. +- +-SSEEEE AALLSSOO +- getservbyname(3), editrc(5), services(5), ftpd(8) +- +-SSTTAANNDDAARRDDSS +- ffttpp attempts to be compliant with RRFFCC 995599, RRFFCC 11112233, RRFFCC 11773388, RRFFCC 22006688, +- RRFFCC 22338899, RRFFCC 22442288, RRFFCC 22773322, and ddrraafftt--iieettff--ffttppeexxtt--mmllsstt--1111. +- +-HHIISSTTOORRYY +- The ffttpp command appeared in 4.2BSD. +- +- Various features such as command line editing, context sensitive command +- and file completion, dynamic progress bar, automatic fetching of files +- and URLs, modification time preservation, transfer rate throttling, con- +- figurable command line prompt, and other enhancements over the standard +- BSD ffttpp were implemented in NetBSD 1.3 and later releases by Luke Mewburn +- <lukem@netbsd.org>. +- +- IPv6 support was added by the WIDE/KAME project (but may not be present +- in all non-NetBSD versions of this program, depending if the operating +- system supports IPv6 in a similar manner to KAME). +- +-BBUUGGSS +- Correct execution of many commands depends upon proper behavior by the +- remote server. +- +- An error in the treatment of carriage returns in the 4.2BSD ascii-mode +- transfer code has been corrected. This correction may result in incor- +- rect transfers of binary files to and from 4.2BSD servers using the ascii +- type. Avoid this problem by using the binary image type. +- +- ffttpp assumes that all IPv4 mapped addresses (IPv6 addresses with a form +- like ::ffff:10.1.1.1) indicate IPv4 destinations which can be handled by +- AF_INET sockets. However, in certain IPv6 network configurations, this +- assumption is not true. In such an environment, IPv4 mapped addresses +- must be passed to AF_INET6 sockets directly. For example, if your site +- uses a SIIT translator for IPv6-to-IPv4 translation, ffttpp is unable to +- support your configuration. +- +-NetBSD 1.6_BETA1 May 18, 2002 16 +diff -Nru src/ftp_var.h /home/spock/ftp/ftp_var.h +--- src/ftp_var.h Sat Jun 15 05:40:36 2002 ++++ /home/spock/ftp/ftp_var.h Thu Jun 12 02:02:11 2003 +@@ -1,7 +1,7 @@ +-/* $NetBSD: ftp_var.h,v 1.62 2001/12/26 09:40:16 lukem Exp $ */ ++/* $NetBSD: ftp_var.h,v 1.64 2003/01/21 16:08:07 jhawk Exp $ */ + + /*- +- * Copyright (c) 1996-2001 The NetBSD Foundation, Inc. ++ * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation +@@ -111,14 +111,20 @@ + #define NO_PROGRESS + #endif + ++#include <sys/param.h> ++ ++#include <netinet/in.h> ++#include <arpa/inet.h> ++ ++#include <setjmp.h> ++#include <stringlist.h> ++ + #ifndef NO_EDITCOMPLETE + #include <histedit.h> + #endif /* !NO_EDITCOMPLETE */ + +-typedef void (*sigfunc)(int); +- + #include "extern.h" +- ++#include "progressbar.h" + + /* + * Format of command table. +@@ -175,7 +181,6 @@ + + #define HASHBYTES 1024 /* default mark for `hash' command */ + #define DEFAULTINCR 1024 /* default increment for `rate' command */ +-#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */ + + #define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */ + #define HTTP_PORT 80 /* default if ! getservbyname("http/tcp") */ +@@ -204,9 +209,7 @@ + GLOBAL int hash; /* print # for each buffer transferred */ + GLOBAL int mark; /* number of bytes between hashes */ + GLOBAL int sendport; /* use PORT/LPRT cmd for each data connection */ +-GLOBAL int verbose; /* print messages coming back from server */ + GLOBAL int connected; /* 1 = connected to server, -1 = logged in */ +-GLOBAL int fromatty; /* input is from a terminal */ + GLOBAL int interactive; /* interactively prompt on m* cmds */ + GLOBAL int confirmrest; /* confirm rest of current m* cmd */ + GLOBAL int debug; /* debugging level */ +@@ -223,7 +226,6 @@ + GLOBAL int ntflag; /* use ntin ntout tables for name translation */ + GLOBAL int mapflag; /* use mapin mapout templates on file names */ + GLOBAL int preserve; /* preserve modification time on files */ +-GLOBAL int progress; /* display transfer progress bar */ + GLOBAL int code; /* return/reply code for ftp command */ + GLOBAL int crflag; /* if 1, strip car. rets. on ascii gets */ + GLOBAL int passivemode; /* passive mode enabled */ +@@ -252,9 +254,7 @@ + GLOBAL int rate_put; /* maximum put xfer rate */ + GLOBAL int rate_put_incr; /* increment for put xfer rate */ + GLOBAL int retry_connect; /* seconds between retrying connection */ +-GLOBAL int ttywidth; /* width of tty */ + GLOBAL char *tmpdir; /* temporary directory */ +-GLOBAL FILE *ttyout; /* stdout, or stderr if retrieving to stdout */ + GLOBAL int epsv4; /* use EPSV/EPRT on IPv4 connections */ + GLOBAL int epsv4bad; /* EPSV doesn't work on the current server */ + GLOBAL int editing; /* command line editing enabled */ +@@ -268,10 +268,7 @@ + GLOBAL size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ + #endif /* !NO_EDITCOMPLETE */ + +-GLOBAL off_t bytes; /* current # of bytes read */ +-GLOBAL off_t filesize; /* size of file being transferred */ + GLOBAL char *direction; /* direction transfer is occurring */ +-GLOBAL off_t restart_point; /* offset to restart transfer */ + + GLOBAL char *hostname; /* name of host connected to */ + GLOBAL int unix_server; /* server is unix, can use binary for ascii */ +@@ -287,8 +284,6 @@ + GLOBAL char *outfile; /* filename to output URLs to */ + GLOBAL int restartautofetch; /* restart auto-fetch */ + +-GLOBAL sigjmp_buf toplevel; /* non-local goto stuff for cmd scanner */ +- + GLOBAL char line[FTPBUFLEN]; /* input line buffer */ + GLOBAL char *stringbase; /* current scan point in line buffer */ + GLOBAL char argbuf[FTPBUFLEN]; /* argument storage buffer */ +@@ -336,29 +331,7 @@ + #endif + + #ifdef NO_LONG_LONG +-# define LLF "%ld" +-# define LLFP(x) "%" x "ld" +-# define LLT long +-# define ULLF "%lu" +-# define ULLFP(x) "%" x "lu" +-# define ULLT unsigned long + # define STRTOLL(x,y,z) strtol(x,y,z) + #else +-#if HAVE_PRINTF_QD +-# define LLF "%qd" +-# define LLFP(x) "%" x "qd" +-# define LLT long long +-# define ULLF "%qu" +-# define ULLFP(x) "%" x "qu" +-# define ULLT unsigned long long +-# define STRTOLL(x,y,z) strtoll(x,y,z) +-#else +-# define LLF "%lld" +-# define LLFP(x) "%" x "lld" +-# define LLT long long +-# define ULLF "%llu" +-# define ULLFP(x) "%" x "llu" +-# define ULLT unsigned long long + # define STRTOLL(x,y,z) strtoll(x,y,z) +-#endif + #endif +diff -Nru src/main.c /home/spock/ftp/main.c +--- src/main.c Sat Jun 15 05:40:36 2002 ++++ /home/spock/ftp/main.c Thu Jun 12 02:02:11 2003 +@@ -1,4 +1,4 @@ +-/* $NetBSD: main.c,v 1.82 2002/06/05 13:51:54 lukem Exp $ */ ++/* $NetBSD: main.c,v 1.84 2003/05/14 14:31:00 wiz Exp $ */ + + /*- + * Copyright (c) 1996-2002 The NetBSD Foundation, Inc. +@@ -98,11 +98,36 @@ + * SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> ++#ifndef lint ++__COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\ ++ The Regents of the University of California. All rights reserved.\n"); ++#endif /* not lint */ ++ ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94"; ++#else ++__RCSID("$NetBSD: main.c,v 1.84 2003/05/14 14:31:00 wiz Exp $"); ++#endif ++#endif /* not lint */ ++ + /* + * FTP User Program -- Command Interface. + */ ++#include <sys/types.h> ++#include <sys/socket.h> + +-#include "lukemftp.h" ++#include <err.h> ++#include <errno.h> ++#include <netdb.h> ++#include <paths.h> ++#include <pwd.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> ++#include <locale.h> + + #define GLOBAL /* force GLOBAL decls in ftp_var.h to be declared */ + #include "ftp_var.h" +@@ -123,9 +148,7 @@ + char *cp, *ep, *anonuser, *anonpass, *upload_path; + int dumbterm, s, len, isupload; + +-#if 0 /* XXX */ + setlocale(LC_ALL, ""); +-#endif + setprogname(argv[0]); + + ftpport = "ftp"; +@@ -258,7 +281,7 @@ + } + } + +- while ((ch = getopt(argc, argv, "46AadefginN:o:pP:r:RtT:u:vV")) != -1) { ++ while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:RtT:u:vV")) != -1) { + switch (ch) { + case '4': + family = AF_INET; +@@ -330,6 +353,12 @@ + ftpport = optarg; + break; + ++ case 'q': ++ quit_time = strtol(optarg, &ep, 10); ++ if (quit_time < 1 || *ep != '\0') ++ errx(1, "bad quit value: %s", optarg); ++ break; ++ + case 'r': + retry_connect = strtol(optarg, &ep, 10); + if (retry_connect < 1 || *ep != '\0') +@@ -1003,6 +1032,6 @@ + " [-T dir,max[,inc][[user@]host [port]]] [host:path[/]]\n" + " [file:///file] [ftp://[user[:pass]@]host[:port]/path[/]]\n" + " [http://[user[:pass]@]host[:port]/path] [...]\n" +-" %s -u url file [...]\n", progname, progname); ++" %s -u URL file [...]\n", progname, progname); + exit(1); + } +diff -Nru src/progressbar.c /home/spock/ftp/progressbar.c +--- src/progressbar.c Wed Dec 31 19:00:00 1969 ++++ /home/spock/ftp/progressbar.c Thu Jun 12 02:02:11 2003 +@@ -0,0 +1,460 @@ ++/* $NetBSD: progressbar.c,v 1.3 2003/02/28 09:53:49 lukem Exp $ */ ++ ++/*- ++ * Copyright (c) 1997-2003 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Luke Mewburn. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, ++ * NASA Ames Research Center. ++ * ++ * 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 NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> ++#ifndef lint ++__RCSID("$NetBSD: progressbar.c,v 1.3 2003/02/28 09:53:49 lukem Exp $"); ++#endif /* not lint */ ++ ++/* ++ * FTP User Program -- Misc support routines ++ */ ++#include <sys/types.h> ++#include <sys/param.h> ++ ++#include <err.h> ++#include <errno.h> ++#include <signal.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <time.h> ++#include <tzfile.h> ++#include <unistd.h> ++ ++#include "progressbar.h" ++ ++#if !defined(NO_PROGRESS) ++/* ++ * return non-zero if we're the current foreground process ++ */ ++int ++foregroundproc(void) ++{ ++ static pid_t pgrp = -1; ++ ++ if (pgrp == -1) ++ pgrp = getpgrp(); ++ ++ return (tcgetpgrp(fileno(ttyout)) == pgrp); ++} ++#endif /* !defined(NO_PROGRESS) */ ++ ++ ++#ifndef NO_PROGRESS ++static void updateprogressmeter(int); ++ ++/* ++ * SIGALRM handler to update the progress meter ++ */ ++static void ++updateprogressmeter(int dummy) ++{ ++ int oerrno = errno; ++ ++ progressmeter(0); ++ errno = oerrno; ++} ++#endif /* NO_PROGRESS */ ++ ++ ++/* ++ * List of order of magnitude prefixes. ++ * The last is `P', as 2^64 = 16384 Petabytes ++ */ ++static const char prefixes[] = " KMGTP"; ++ ++/* ++ * Display a transfer progress bar if progress is non-zero. ++ * SIGALRM is hijacked for use by this function. ++ * - Before the transfer, set filesize to size of file (or -1 if unknown), ++ * and call with flag = -1. This starts the once per second timer, ++ * and a call to updateprogressmeter() upon SIGALRM. ++ * - During the transfer, updateprogressmeter will call progressmeter ++ * with flag = 0 ++ * - After the transfer, call with flag = 1 ++ */ ++static struct timeval start; ++static struct timeval lastupdate; ++ ++#define BUFLEFT (sizeof(buf) - len) ++ ++void ++progressmeter(int flag) ++{ ++ static off_t lastsize; ++ off_t cursize; ++ struct timeval now, wait; ++#ifndef NO_PROGRESS ++ struct timeval td; ++ off_t abbrevsize, bytespersec; ++ double elapsed; ++ int ratio, barlength, i, len, remaining; ++ ++ /* ++ * Work variables for progress bar. ++ * ++ * XXX: if the format of the progress bar changes ++ * (especially the number of characters in the ++ * `static' portion of it), be sure to update ++ * these appropriately. ++ */ ++ char buf[256]; /* workspace for progress bar */ ++#define BAROVERHEAD 43 /* non `*' portion of progress bar */ ++ /* ++ * stars should contain at least ++ * sizeof(buf) - BAROVERHEAD entries ++ */ ++ static const char stars[] = ++"*****************************************************************************" ++"*****************************************************************************" ++"*****************************************************************************"; ++ ++#endif ++ ++ if (flag == -1) { ++ (void)gettimeofday(&start, NULL); ++ lastupdate = start; ++ lastsize = restart_point; ++ } ++ ++ (void)gettimeofday(&now, NULL); ++ cursize = bytes + restart_point; ++ timersub(&now, &lastupdate, &wait); ++ if (cursize > lastsize) { ++ lastupdate = now; ++ lastsize = cursize; ++ wait.tv_sec = 0; ++ } else { ++#ifndef STANDALONE_PROGRESS ++ if (quit_time > 0 && wait.tv_sec > quit_time) { ++ len = snprintf(buf, sizeof(buf), "\r\n%s: " ++ "transfer aborted because stalled for %lu sec.\r\n", ++ getprogname(), (unsigned long)wait.tv_sec); ++ (void)write(fileno(ttyout), buf, len); ++ (void)xsignal(SIGALRM, SIG_DFL); ++ alarmtimer(0); ++ siglongjmp(toplevel, 1); ++ } ++#endif /* !STANDALONE_PROGRESS */ ++ } ++ /* ++ * Always set the handler even if we are not the foreground process. ++ */ ++#ifdef STANDALONE_PROGRESS ++ if (progress) { ++#else ++ if (quit_time > 0 || progress) { ++#endif /* !STANDALONE_PROGRESS */ ++ if (flag == -1) { ++ (void)xsignal_restart(SIGALRM, updateprogressmeter, 1); ++ alarmtimer(1); /* set alarm timer for 1 Hz */ ++ } else if (flag == 1) { ++ (void)xsignal(SIGALRM, SIG_DFL); ++ alarmtimer(0); ++ } ++ } ++#ifndef NO_PROGRESS ++ if (!progress) ++ return; ++ len = 0; ++ ++ /* ++ * print progress bar only if we are foreground process. ++ */ ++ if (! foregroundproc()) ++ return; ++ ++ len += snprintf(buf + len, BUFLEFT, "\r"); ++ if (filesize > 0) { ++ ratio = (int)((double)cursize * 100.0 / (double)filesize); ++ ratio = MAX(ratio, 0); ++ ratio = MIN(ratio, 100); ++ len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio); ++ ++ /* ++ * calculate the length of the `*' bar, ensuring that ++ * the number of stars won't exceed the buffer size ++ */ ++ barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD; ++ if (barlength > 0) { ++ i = barlength * ratio / 100; ++ len += snprintf(buf + len, BUFLEFT, ++ "|%.*s%*s|", i, stars, barlength - i, ""); ++ } ++ } ++ ++ abbrevsize = cursize; ++ for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++) ++ abbrevsize >>= 10; ++ len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ", ++ (LLT)abbrevsize, ++ prefixes[i], ++ i == 0 ? ' ' : 'B'); ++ ++ timersub(&now, &start, &td); ++ elapsed = td.tv_sec + (td.tv_usec / 1000000.0); ++ ++ bytespersec = 0; ++ if (bytes > 0) { ++ bytespersec = bytes; ++ if (elapsed > 0.0) ++ bytespersec /= elapsed; ++ } ++ for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) ++ bytespersec >>= 10; ++ len += snprintf(buf + len, BUFLEFT, ++ " " LLFP("3") ".%02d %cB/s ", ++ (LLT)(bytespersec / 1024), ++ (int)((bytespersec % 1024) * 100 / 1024), ++ prefixes[i]); ++ ++ if (filesize > 0) { ++ if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) { ++ len += snprintf(buf + len, BUFLEFT, " --:-- ETA"); ++ } else if (wait.tv_sec >= STALLTIME) { ++ len += snprintf(buf + len, BUFLEFT, " - stalled -"); ++ } else { ++ remaining = (int) ++ ((filesize - restart_point) / (bytes / elapsed) - ++ elapsed); ++ if (remaining >= 100 * SECSPERHOUR) ++ len += snprintf(buf + len, BUFLEFT, ++ " --:-- ETA"); ++ else { ++ i = remaining / SECSPERHOUR; ++ if (i) ++ len += snprintf(buf + len, BUFLEFT, ++ "%2d:", i); ++ else ++ len += snprintf(buf + len, BUFLEFT, ++ " "); ++ i = remaining % SECSPERHOUR; ++ len += snprintf(buf + len, BUFLEFT, ++ "%02d:%02d ETA", i / 60, i % 60); ++ } ++ } ++ } ++ if (flag == 1) ++ len += snprintf(buf + len, BUFLEFT, "\n"); ++ (void)write(fileno(ttyout), buf, len); ++ ++#endif /* !NO_PROGRESS */ ++} ++ ++#ifndef STANDALONE_PROGRESS ++/* ++ * Display transfer statistics. ++ * Requires start to be initialised by progressmeter(-1), ++ * direction to be defined by xfer routines, and filesize and bytes ++ * to be updated by xfer routines ++ * If siginfo is nonzero, an ETA is displayed, and the output goes to stderr ++ * instead of ttyout. ++ */ ++void ++ptransfer(int siginfo) ++{ ++ struct timeval now, td, wait; ++ double elapsed; ++ off_t bytespersec; ++ int remaining, hh, i, len; ++ ++ char buf[256]; /* Work variable for transfer status. */ ++ ++ if (!verbose && !progress && !siginfo) ++ return; ++ ++ (void)gettimeofday(&now, NULL); ++ timersub(&now, &start, &td); ++ elapsed = td.tv_sec + (td.tv_usec / 1000000.0); ++ bytespersec = 0; ++ if (bytes > 0) { ++ bytespersec = bytes; ++ if (elapsed > 0.0) ++ bytespersec /= elapsed; ++ } ++ len = 0; ++ len += snprintf(buf + len, BUFLEFT, LLF " byte%s %s in ", ++ (LLT)bytes, bytes == 1 ? "" : "s", direction); ++ remaining = (int)elapsed; ++ if (remaining > SECSPERDAY) { ++ int days; ++ ++ days = remaining / SECSPERDAY; ++ remaining %= SECSPERDAY; ++ len += snprintf(buf + len, BUFLEFT, ++ "%d day%s ", days, days == 1 ? "" : "s"); ++ } ++ hh = remaining / SECSPERHOUR; ++ remaining %= SECSPERHOUR; ++ if (hh) ++ len += snprintf(buf + len, BUFLEFT, "%2d:", hh); ++ len += snprintf(buf + len, BUFLEFT, ++ "%02d:%02d ", remaining / 60, remaining % 60); ++ ++ for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) ++ bytespersec >>= 10; ++ len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)", ++ (LLT)(bytespersec / 1024), ++ (int)((bytespersec % 1024) * 100 / 1024), ++ prefixes[i]); ++ ++ if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0 ++ && bytes + restart_point <= filesize) { ++ remaining = (int)((filesize - restart_point) / ++ (bytes / elapsed) - elapsed); ++ hh = remaining / SECSPERHOUR; ++ remaining %= SECSPERHOUR; ++ len += snprintf(buf + len, BUFLEFT, " ETA: "); ++ if (hh) ++ len += snprintf(buf + len, BUFLEFT, "%2d:", hh); ++ len += snprintf(buf + len, BUFLEFT, "%02d:%02d", ++ remaining / 60, remaining % 60); ++ timersub(&now, &lastupdate, &wait); ++ if (wait.tv_sec >= STALLTIME) ++ len += snprintf(buf + len, BUFLEFT, " (stalled)"); ++ } ++ len += snprintf(buf + len, BUFLEFT, "\n"); ++ (void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len); ++} ++ ++/* ++ * SIG{INFO,QUIT} handler to print transfer stats if a transfer is in progress ++ */ ++void ++psummary(int notused) ++{ ++ int oerrno = errno; ++ ++ if (bytes > 0) { ++ if (fromatty) ++ write(fileno(ttyout), "\n", 1); ++ ptransfer(1); ++ } ++ errno = oerrno; ++} ++#endif /* !STANDALONE_PROGRESS */ ++ ++ ++/* ++ * Set the SIGALRM interval timer for wait seconds, 0 to disable. ++ */ ++void ++alarmtimer(int wait) ++{ ++ struct itimerval itv; ++ ++ itv.it_value.tv_sec = wait; ++ itv.it_value.tv_usec = 0; ++ itv.it_interval = itv.it_value; ++ setitimer(ITIMER_REAL, &itv, NULL); ++} ++ ++ ++/* ++ * Install a POSIX signal handler, allowing the invoker to set whether ++ * the signal should be restartable or not ++ */ ++sigfunc ++xsignal_restart(int sig, sigfunc func, int restartable) ++{ ++ struct sigaction act, oact; ++ act.sa_handler = func; ++ ++ sigemptyset(&act.sa_mask); ++#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */ ++ act.sa_flags = restartable ? SA_RESTART : 0; ++#elif defined(SA_INTERRUPT) /* SunOS 4.x */ ++ act.sa_flags = restartable ? 0 : SA_INTERRUPT; ++#else ++#error "system must have SA_RESTART or SA_INTERRUPT" ++#endif ++ if (sigaction(sig, &act, &oact) < 0) ++ return (SIG_ERR); ++ return (oact.sa_handler); ++} ++ ++/* ++ * Install a signal handler with the `restartable' flag set dependent upon ++ * which signal is being set. (This is a wrapper to xsignal_restart()) ++ */ ++sigfunc ++xsignal(int sig, sigfunc func) ++{ ++ int restartable; ++ ++ /* ++ * Some signals print output or change the state of the process. ++ * There should be restartable, so that reads and writes are ++ * not affected. Some signals should cause program flow to change; ++ * these signals should not be restartable, so that the system call ++ * will return with EINTR, and the program will go do something ++ * different. If the signal handler calls longjmp() or siglongjmp(), ++ * it doesn't matter if it's restartable. ++ */ ++ ++ switch(sig) { ++#ifdef SIGINFO ++ case SIGINFO: ++#endif ++ case SIGQUIT: ++ case SIGUSR1: ++ case SIGUSR2: ++ case SIGWINCH: ++ restartable = 1; ++ break; ++ ++ case SIGALRM: ++ case SIGINT: ++ case SIGPIPE: ++ restartable = 0; ++ break; ++ ++ default: ++ /* ++ * This is unpleasant, but I don't know what would be better. ++ * Right now, this "can't happen" ++ */ ++ errx(1, "xsignal_restart called with signal %d", sig); ++ } ++ ++ return(xsignal_restart(sig, func, restartable)); ++} +diff -Nru src/progressbar.h /home/spock/ftp/progressbar.h +--- src/progressbar.h Wed Dec 31 19:00:00 1969 ++++ /home/spock/ftp/progressbar.h Thu Jun 12 02:02:11 2003 +@@ -0,0 +1,99 @@ ++/* $NetBSD: progressbar.h,v 1.3 2003/02/28 09:53:49 lukem Exp $ */ ++ ++/*- ++ * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. ++ * All rights reserved. ++ * ++ * This code is derived from software contributed to The NetBSD Foundation ++ * by Luke Mewburn. ++ * ++ * 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 NetBSD ++ * Foundation, Inc. and its contributors. ++ * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. ++ */ ++ ++#ifndef STANDALONE_PROGRESS ++#include <setjmp.h> ++#endif /* !STANDALONE_PROGRESS */ ++ ++#ifndef GLOBAL ++#define GLOBAL extern ++#endif ++ ++ ++#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */ ++ ++typedef void (*sigfunc)(int); ++ ++ ++GLOBAL FILE *ttyout; /* stdout, or stderr if retrieving to stdout */ ++ ++GLOBAL int progress; /* display transfer progress bar */ ++GLOBAL int ttywidth; /* width of tty */ ++ ++GLOBAL off_t bytes; /* current # of bytes read */ ++GLOBAL off_t filesize; /* size of file being transferred */ ++GLOBAL off_t restart_point; /* offset to restart transfer */ ++ ++ ++#ifndef STANDALONE_PROGRESS ++GLOBAL int fromatty; /* input is from a terminal */ ++GLOBAL int verbose; /* print messages coming back from server */ ++GLOBAL int quit_time; /* maximum time to wait if stalled */ ++ ++GLOBAL char *direction; /* direction transfer is occurring */ ++ ++GLOBAL sigjmp_buf toplevel; /* non-local goto stuff for cmd scanner */ ++#endif /* !STANDALONE_PROGRESS */ ++ ++int foregroundproc(void); ++void alarmtimer(int); ++void progressmeter(int); ++sigfunc xsignal(int, sigfunc); ++sigfunc xsignal_restart(int, sigfunc, int); ++ ++#ifndef STANDALONE_PROGRESS ++void psummary(int); ++void ptransfer(int); ++#endif /* !STANDALONE_PROGRESS */ ++ ++ ++#ifdef NO_LONG_LONG ++# define LLF "%ld" ++# define LLFP(x) "%" x "ld" ++# define LLT long ++# define ULLF "%lu" ++# define ULLFP(x) "%" x "lu" ++# define ULLT unsigned long ++#else ++# define LLF "%lld" ++# define LLFP(x) "%" x "lld" ++# define LLT long long ++# define ULLF "%llu" ++# define ULLFP(x) "%" x "llu" ++# define ULLT unsigned long long ++#endif +diff -Nru src/ruserpass.c /home/spock/ftp/ruserpass.c +--- src/ruserpass.c Sat Jun 15 05:40:36 2002 ++++ /home/spock/ftp/ruserpass.c Thu Jun 12 02:02:11 2003 +@@ -33,7 +33,26 @@ + * SUCH DAMAGE. + */ + +-#include "lukemftp.h" ++#include <sys/cdefs.h> ++#ifndef lint ++#if 0 ++static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; ++#else ++__RCSID("$NetBSD: ruserpass.c,v 1.28 2000/11/15 00:11:04 lukem Exp $"); ++#endif ++#endif /* not lint */ ++ ++#include <sys/types.h> ++#include <sys/stat.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <errno.h> ++#include <netdb.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <unistd.h> + + #include "ftp_var.h" + +diff -Nru src/util.c /home/spock/ftp/util.c +--- src/util.c Sat Jun 15 05:40:37 2002 ++++ /home/spock/ftp/util.c Thu Jun 12 02:02:11 2003 +@@ -1,7 +1,7 @@ +-/* $NetBSD: util.c,v 1.107 2002/06/05 10:20:50 lukem Exp $ */ ++/* $NetBSD: util.c,v 1.111 2003/02/28 09:54:51 lukem Exp $ */ + + /*- +- * Copyright (c) 1997-2002 The NetBSD Foundation, Inc. ++ * Copyright (c) 1997-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation +@@ -73,11 +73,36 @@ + * SUCH DAMAGE. + */ + ++#include <sys/cdefs.h> ++#ifndef lint ++__RCSID("$NetBSD: util.c,v 1.111 2003/02/28 09:54:51 lukem Exp $"); ++#endif /* not lint */ ++ + /* + * FTP User Program -- Misc support routines + */ +- +-#include "lukemftp.h" ++#include <sys/types.h> ++#include <sys/socket.h> ++#include <sys/ioctl.h> ++#include <sys/time.h> ++#include <netinet/in.h> ++#include <arpa/ftp.h> ++ ++#include <ctype.h> ++#include <err.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <glob.h> ++#include <signal.h> ++#include <limits.h> ++#include <netdb.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <string.h> ++#include <termios.h> ++#include <time.h> ++#include <tzfile.h> ++#include <unistd.h> + + #include "ftp_var.h" + +@@ -775,303 +800,6 @@ + code = ocode; + } + +-#ifndef NO_PROGRESS +- +-/* +- * return non-zero if we're the current foreground process +- */ +-int +-foregroundproc(void) +-{ +- static pid_t pgrp = -1; +- +- if (pgrp == -1) +-#if GETPGRP_VOID +- pgrp = getpgrp(); +-#else /* ! GETPGRP_VOID */ +- pgrp = getpgrp(0); +-#endif /* ! GETPGRP_VOID */ +- +- return (tcgetpgrp(fileno(ttyout)) == pgrp); +-} +- +- +-static void updateprogressmeter(int); +- +-/* +- * SIGALRM handler to update the progress meter +- */ +-static void +-updateprogressmeter(int dummy) +-{ +- int oerrno = errno; +- +- progressmeter(0); +- errno = oerrno; +-} +-#endif /* NO_PROGRESS */ +- +- +-/* +- * List of order of magnitude prefixes. +- * The last is `P', as 2^64 = 16384 Petabytes +- */ +-static const char prefixes[] = " KMGTP"; +- +-/* +- * Display a transfer progress bar if progress is non-zero. +- * SIGALRM is hijacked for use by this function. +- * - Before the transfer, set filesize to size of file (or -1 if unknown), +- * and call with flag = -1. This starts the once per second timer, +- * and a call to updateprogressmeter() upon SIGALRM. +- * - During the transfer, updateprogressmeter will call progressmeter +- * with flag = 0 +- * - After the transfer, call with flag = 1 +- */ +-static struct timeval start; +-static struct timeval lastupdate; +- +-#define BUFLEFT (sizeof(buf) - len) +- +-void +-progressmeter(int flag) +-{ +- static off_t lastsize; +-#ifndef NO_PROGRESS +- struct timeval now, td, wait; +- off_t cursize, abbrevsize, bytespersec; +- double elapsed; +- int ratio, barlength, i, len, remaining; +- +- /* +- * Work variables for progress bar. +- * +- * XXX: if the format of the progress bar changes +- * (especially the number of characters in the +- * `static' portion of it), be sure to update +- * these appropriately. +- */ +- char buf[256]; /* workspace for progress bar */ +-#define BAROVERHEAD 43 /* non `*' portion of progress bar */ +- /* +- * stars should contain at least +- * sizeof(buf) - BAROVERHEAD entries +- */ +- const char stars[] = +-"*****************************************************************************" +-"*****************************************************************************" +-"*****************************************************************************"; +- +-#endif +- +- if (flag == -1) { +- (void)gettimeofday(&start, NULL); +- lastupdate = start; +- lastsize = restart_point; +- } +-#ifndef NO_PROGRESS +- if (!progress) +- return; +- len = 0; +- +- /* +- * print progress bar only if we are foreground process. +- */ +- if (! foregroundproc()) +- return; +- +- (void)gettimeofday(&now, NULL); +- cursize = bytes + restart_point; +- timersub(&now, &lastupdate, &wait); +- if (cursize > lastsize) { +- lastupdate = now; +- lastsize = cursize; +- wait.tv_sec = 0; +- } +- +- len += snprintf(buf + len, BUFLEFT, "\r"); +- if (filesize > 0) { +- ratio = (int)((double)cursize * 100.0 / (double)filesize); +- ratio = MAX(ratio, 0); +- ratio = MIN(ratio, 100); +- len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio); +- +- /* +- * calculate the length of the `*' bar, ensuring that +- * the number of stars won't exceed the buffer size +- */ +- barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD; +- if (barlength > 0) { +- i = barlength * ratio / 100; +- len += snprintf(buf + len, BUFLEFT, +- "|%.*s%*s|", i, stars, barlength - i, ""); +- } +- } +- +- abbrevsize = cursize; +- for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++) +- abbrevsize >>= 10; +- len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ", +- (LLT)abbrevsize, +- prefixes[i], +- i == 0 ? ' ' : 'B'); +- +- timersub(&now, &start, &td); +- elapsed = td.tv_sec + (td.tv_usec / 1000000.0); +- +- bytespersec = 0; +- if (bytes > 0) { +- bytespersec = bytes; +- if (elapsed > 0.0) +- bytespersec /= elapsed; +- } +- for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) +- bytespersec >>= 10; +- len += snprintf(buf + len, BUFLEFT, +- " " LLFP("3") ".%02d %cB/s ", +- (LLT)(bytespersec / 1024), +- (int)((bytespersec % 1024) * 100 / 1024), +- prefixes[i]); +- +- if (filesize > 0) { +- if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) { +- len += snprintf(buf + len, BUFLEFT, " --:-- ETA"); +- } else if (flag == 1) { +- i = elapsed / SECSPERHOUR; +- if (i) +- len += snprintf(buf + len, BUFLEFT, "%2d:", i); +- else +- len += snprintf(buf + len, BUFLEFT, " "); +- i = (int)elapsed % SECSPERHOUR; +- len += snprintf(buf + len, BUFLEFT, +- "%02d:%02d ", i / 60, i % 60); +- } else if (wait.tv_sec >= STALLTIME) { +- len += snprintf(buf + len, BUFLEFT, " - stalled -"); +- } else { +- remaining = (int) +- ((filesize - restart_point) / (bytes / elapsed) - +- elapsed); +- if (remaining >= 100 * SECSPERHOUR) +- len += snprintf(buf + len, BUFLEFT, +- " --:-- ETA"); +- else { +- i = remaining / SECSPERHOUR; +- if (i) +- len += snprintf(buf + len, BUFLEFT, +- "%2d:", i); +- else +- len += snprintf(buf + len, BUFLEFT, +- " "); +- i = remaining % SECSPERHOUR; +- len += snprintf(buf + len, BUFLEFT, +- "%02d:%02d ETA", i / 60, i % 60); +- } +- } +- } +- if (flag == 1) +- len += snprintf(buf + len, BUFLEFT, "\n"); +- (void)write(fileno(ttyout), buf, len); +- +- if (flag == -1) { +- (void)xsignal_restart(SIGALRM, updateprogressmeter, 1); +- alarmtimer(1); /* set alarm timer for 1 Hz */ +- } else if (flag == 1) { +- (void)xsignal(SIGALRM, SIG_DFL); +- alarmtimer(0); +- } +-#endif /* !NO_PROGRESS */ +-} +- +-/* +- * Display transfer statistics. +- * Requires start to be initialised by progressmeter(-1), +- * direction to be defined by xfer routines, and filesize and bytes +- * to be updated by xfer routines +- * If siginfo is nonzero, an ETA is displayed, and the output goes to stderr +- * instead of ttyout. +- */ +-void +-ptransfer(int siginfo) +-{ +- struct timeval now, td, wait; +- double elapsed; +- off_t bytespersec; +- int remaining, hh, i, len; +- +- char buf[256]; /* Work variable for transfer status. */ +- +- if (!verbose && !progress && !siginfo) +- return; +- +- (void)gettimeofday(&now, NULL); +- timersub(&now, &start, &td); +- elapsed = td.tv_sec + (td.tv_usec / 1000000.0); +- bytespersec = 0; +- if (bytes > 0) { +- bytespersec = bytes; +- if (elapsed > 0.0) +- bytespersec /= elapsed; +- } +- len = 0; +- len += snprintf(buf + len, BUFLEFT, LLF " byte%s %s in ", +- (LLT)bytes, bytes == 1 ? "" : "s", direction); +- remaining = (int)elapsed; +- if (remaining > SECSPERDAY) { +- int days; +- +- days = remaining / SECSPERDAY; +- remaining %= SECSPERDAY; +- len += snprintf(buf + len, BUFLEFT, +- "%d day%s ", days, days == 1 ? "" : "s"); +- } +- hh = remaining / SECSPERHOUR; +- remaining %= SECSPERHOUR; +- if (hh) +- len += snprintf(buf + len, BUFLEFT, "%2d:", hh); +- len += snprintf(buf + len, BUFLEFT, +- "%02d:%02d ", remaining / 60, remaining % 60); +- +- for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) +- bytespersec >>= 10; +- len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)", +- (LLT)(bytespersec / 1024), +- (int)((bytespersec % 1024) * 100 / 1024), +- prefixes[i]); +- +- if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0 +- && bytes + restart_point <= filesize) { +- remaining = (int)((filesize - restart_point) / +- (bytes / elapsed) - elapsed); +- hh = remaining / SECSPERHOUR; +- remaining %= SECSPERHOUR; +- len += snprintf(buf + len, BUFLEFT, " ETA: "); +- if (hh) +- len += snprintf(buf + len, BUFLEFT, "%2d:", hh); +- len += snprintf(buf + len, BUFLEFT, "%02d:%02d", +- remaining / 60, remaining % 60); +- timersub(&now, &lastupdate, &wait); +- if (wait.tv_sec >= STALLTIME) +- len += snprintf(buf + len, BUFLEFT, " (stalled)"); +- } +- len += snprintf(buf + len, BUFLEFT, "\n"); +- (void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len); +-} +- +-/* +- * SIG{INFO,QUIT} handler to print transfer stats if a transfer is in progress +- */ +-void +-psummary(int notused) +-{ +- int oerrno = errno; +- +- if (bytes > 0) { +- if (fromatty) +- write(fileno(ttyout), "\n", 1); +- ptransfer(1); +- } +- errno = oerrno; +-} + + /* + * List words in stringlist, vertically arranged +@@ -1158,20 +886,6 @@ + + + /* +- * Set the SIGALRM interval timer for wait seconds, 0 to disable. +- */ +-void +-alarmtimer(int wait) +-{ +- struct itimerval itv; +- +- itv.it_value.tv_sec = wait; +- itv.it_value.tv_usec = 0; +- itv.it_interval = itv.it_value; +- setitimer(ITIMER_REAL, &itv, NULL); +-} +- +-/* + * Setup or cleanup EditLine structures + */ + #ifndef NO_EDITCOMPLETE +@@ -1552,85 +1266,4 @@ + if (s == NULL) + err(1, "Unable to allocate memory for string copy"); + return (s); +-} +- +-/* +- * Install a POSIX signal handler, allowing the invoker to set whether +- * the signal should be restartable or not +- */ +-sigfunc +-xsignal_restart(int sig, sigfunc func, int restartable) +-{ +-#ifdef ultrix /* XXX: this is lame - how do we test sigvec vs. sigaction? */ +- struct sigvec vec, ovec; +- +- vec.sv_handler = func; +- sigemptyset(&vec.sv_mask); +- vec.sv_flags = 0; +- if (sigvec(sig, &vec, &ovec) < 0) +- return (SIG_ERR); +- return (ovec.sv_handler); +-#else /* ! ultrix */ +- struct sigaction act, oact; +- act.sa_handler = func; +- +- sigemptyset(&act.sa_mask); +-#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */ +- act.sa_flags = restartable ? SA_RESTART : 0; +-#elif defined(SA_INTERRUPT) /* SunOS 4.x */ +- act.sa_flags = restartable ? 0 : SA_INTERRUPT; +-#else +-#error "system must have SA_RESTART or SA_INTERRUPT" +-#endif +- if (sigaction(sig, &act, &oact) < 0) +- return (SIG_ERR); +- return (oact.sa_handler); +-#endif /* ! ultrix */ +-} +- +-/* +- * Install a signal handler with the `restartable' flag set dependent upon +- * which signal is being set. (This is a wrapper to xsignal_restart()) +- */ +-sigfunc +-xsignal(int sig, sigfunc func) +-{ +- int restartable; +- +- /* +- * Some signals print output or change the state of the process. +- * There should be restartable, so that reads and writes are +- * not affected. Some signals should cause program flow to change; +- * these signals should not be restartable, so that the system call +- * will return with EINTR, and the program will go do something +- * different. If the signal handler calls longjmp() or siglongjmp(), +- * it doesn't matter if it's restartable. +- */ +- +- switch(sig) { +-#ifdef SIGINFO +- case SIGINFO: +-#endif +- case SIGQUIT: +- case SIGUSR1: +- case SIGUSR2: +- case SIGWINCH: +- restartable = 1; +- break; +- +- case SIGALRM: +- case SIGINT: +- case SIGPIPE: +- restartable = 0; +- break; +- +- default: +- /* +- * This is unpleasant, but I don't know what would be better. +- * Right now, this "can't happen" +- */ +- errx(1, "xsignal_restart called with signal %d", sig); +- } +- +- return(xsignal_restart(sig, func, restartable)); + } +diff -Nru src/version.h /home/spock/ftp/version.h +--- src/version.h Sat Jun 15 05:40:37 2002 ++++ /home/spock/ftp/version.h Thu Jun 12 02:02:11 2003 +@@ -1,6 +1,6 @@ +-/* $NetBSD: version.h,v 1.29 2002/06/05 10:20:51 lukem Exp $ */ ++/* $NetBSD: version.h,v 1.30 2003/02/28 09:54:20 lukem Exp $ */ + /*- +- * Copyright (c) 1999-2002 The NetBSD Foundation, Inc. ++ * Copyright (c) 1999-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation +@@ -40,5 +40,5 @@ + #endif + + #ifndef FTP_VERSION +-#define FTP_VERSION "20020605" ++#define FTP_VERSION "20030228" + #endif diff --git a/contrib/tnftp/install-sh b/contrib/tnftp/install-sh new file mode 100755 index 0000000..e9de238 --- /dev/null +++ b/contrib/tnftp/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/contrib/tnftp/lukemftp.h b/contrib/tnftp/lukemftp.h new file mode 100644 index 0000000..e8d83f6 --- /dev/null +++ b/contrib/tnftp/lukemftp.h @@ -0,0 +1,403 @@ +/* $Id: lukemftp.h,v 1.43 2002/06/10 08:13:01 lukem Exp $ */ + +#define FTP_PRODUCT "lukemftp" +#define FTP_VERSION "1.6-beta2" + +#include "config.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> + +#include <arpa/ftp.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <netdb.h> +#include <pwd.h> +#include <setjmp.h> +#include <signal.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> + +#if HAVE_POLL +# if HAVE_POLL_H +# include <poll.h> +# elif HAVE_SYS_POLL_H +# include <sys/poll.h> +# endif +#elif HAVE_SELECT +# define USE_SELECT +#else +# error "no poll() or select() found" +#endif + +#if HAVE_DIRENT_H +# include <dirent.h> +#else +# define dirent direct +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + +#if HAVE_ERR_H +# include <err.h> +#endif + +#if USE_GLOB_H /* not set by configure; used by other build systems */ +# include <glob.h> +#else +# include "ftpglob.h" +#endif + +#if HAVE_PATHS_H +# include <paths.h> +#endif +#ifndef _PATH_BSHELL +#define _PATH_BSHELL "/bin/sh" +#endif +#ifndef _PATH_TMP +#define _PATH_TMP "/tmp/" +#endif + +typedef struct _stringlist { + char **sl_str; + size_t sl_max; + size_t sl_cur; +} StringList; + +StringList *sl_init(void); +int sl_add(StringList *, char *); +void sl_free(StringList *, int); +char *sl_find(StringList *, char *); + +#if HAVE_TERMCAP_H +# include <termcap.h> +#else +int tgetent(char *, const char *); +char *tgetstr(const char *, char **); +int tgetflag(const char *); +int tgetnum(const char *); +char *tgoto(const char *, int, int); +void tputs(const char *, int, int (*)(int)); +#endif + +#if HAVE_UTIL_H +# include <util.h> +#endif + +#if HAVE_LIBUTIL_H +# include <libutil.h> +#endif + +#if HAVE_VIS_H +# include <vis.h> +#else +# include "ftpvis.h" +#endif + +#if ! HAVE_IN_PORT_T +typedef unsigned short in_port_t; +#endif + +#if ! HAVE_SA_FAMILY_T +typedef unsigned short sa_family_t; +#endif + +#if ! HAVE_SOCKLEN_T +typedef unsigned int socklen_t; +#endif + +#if HAVE_AF_INET6 && HAVE_SOCKADDR_IN6 +# define INET6 +#endif + + +#if ! HAVE_RFC2553_NETDB + + /* RFC 2553 */ +#undef EAI_ADDRFAMILY +#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */ +#undef EAI_AGAIN +#define EAI_AGAIN 2 /* temporary failure in name resolution */ +#undef EAI_BADFLAGS +#define EAI_BADFLAGS 3 /* invalid value for ai_flags */ +#undef EAI_FAIL +#define EAI_FAIL 4 /* non-recoverable failure in name resolution */ +#undef EAI_FAMILY +#define EAI_FAMILY 5 /* ai_family not supported */ +#undef EAI_MEMORY +#define EAI_MEMORY 6 /* memory allocation failure */ +#undef EAI_NODATA +#define EAI_NODATA 7 /* no address associated with hostname */ +#undef EAI_NONAME +#define EAI_NONAME 8 /* hostname nor servname provided, or not known */ +#undef EAI_SERVICE +#define EAI_SERVICE 9 /* servname not supported for ai_socktype */ +#undef EAI_SOCKTYPE +#define EAI_SOCKTYPE 10 /* ai_socktype not supported */ +#undef EAI_SYSTEM +#define EAI_SYSTEM 11 /* system error returned in errno */ + + /* KAME extensions? */ +#undef EAI_BADHINTS +#define EAI_BADHINTS 12 +#undef EAI_PROTOCOL +#define EAI_PROTOCOL 13 +#undef EAI_MAX +#define EAI_MAX 14 + + /* RFC 2553 */ +#undef NI_MAXHOST +#define NI_MAXHOST 1025 +#undef NI_MAXSERV +#define NI_MAXSERV 32 + +#undef NI_NOFQDN +#define NI_NOFQDN 0x00000001 +#undef NI_NUMERICHOST +#define NI_NUMERICHOST 0x00000002 +#undef NI_NAMEREQD +#define NI_NAMEREQD 0x00000004 +#undef NI_NUMERICSERV +#define NI_NUMERICSERV 0x00000008 +#undef NI_DGRAM +#define NI_DGRAM 0x00000010 + + /* RFC 2553 */ +#undef AI_PASSIVE +#define AI_PASSIVE 0x00000001 /* get address to use bind() */ +#undef AI_CANONNAME +#define AI_CANONNAME 0x00000002 /* fill ai_canonname */ + + /* KAME extensions ? */ +#undef AI_NUMERICHOST +#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */ +#undef AI_MASK +#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST) + + /* RFC 2553 */ +#undef AI_ALL +#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ +#undef AI_V4MAPPED_CFG +#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ +#undef AI_ADDRCONFIG +#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ +#undef AI_V4MAPPED +#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */ + +#endif /* ! HAVE_RFC2553_NETDB */ + + +#if ! HAVE_RFC2553_NETDB && ! HAVE_ADDRINFO + +struct addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; + +int getaddrinfo(const char *, const char *, + const struct addrinfo *, struct addrinfo **); +int getnameinfo(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +void freeaddrinfo(struct addrinfo *); +char *gai_strerror(int); + +#endif /* ! HAVE_RFC2553_NETDB && ! HAVE_ADDRINFO */ + + +#if ! HAVE_D_NAMLEN +# define DIRENT_MISSING_D_NAMLEN +#endif + +#if ! HAVE_H_ERRNO_D +extern int h_errno; +#endif +#define HAVE_H_ERRNO 1 /* XXX: an assumption for now... */ + +#if ! HAVE_FCLOSE_D +int fclose(FILE *); +#endif + +#if ! HAVE_GETPASS_D +char *getpass(const char *); +#endif + +#if ! HAVE_OPTARG_D +extern char *optarg; +#endif + +#if ! HAVE_OPTIND_D +extern int optind; +#endif + +#if ! HAVE_PCLOSE_D +int pclose(FILE *); +#endif + +#if ! HAVE_ERR +void err(int, const char *, ...); +void errx(int, const char *, ...); +void warn(const char *, ...); +void warnx(const char *, ...); +#endif + +#if ! HAVE_FGETLN +char *fgetln(FILE *, size_t *); +#endif + +#if ! HAVE_FSEEKO +int fseeko(FILE *, off_t, int); +#endif + +#if ! HAVE_FPARSELN +# define FPARSELN_UNESCESC 0x01 +# define FPARSELN_UNESCCONT 0x02 +# define FPARSELN_UNESCCOMM 0x04 +# define FPARSELN_UNESCREST 0x08 +# define FPARSELN_UNESCALL 0x0f +char *fparseln(FILE *, size_t *, size_t *, const char[3], int); +#endif + +#if ! HAVE_INET_NTOP +const char *inet_ntop(int, const void *, char *, size_t); +#endif + +#if ! HAVE_INET_PTON +int inet_pton(int, const char *, void *); +#endif + +#if ! HAVE_MKSTEMP +int mkstemp(char *); +#endif + +#if ! HAVE_SETPROGNAME +const char *getprogname(void); +void setprogname(const char *); +#endif + +#if ! HAVE_SNPRINTF +int snprintf(char *, size_t, const char *, ...); +#endif + +#if ! HAVE_STRDUP +char *strdup(const char *); +#endif + +#if ! HAVE_STRERROR +char *strerror(int); +#endif + +#if ! HAVE_STRPTIME || ! HAVE_STRPTIME_D +char *strptime(const char *, const char *, struct tm *); +#endif + +#if HAVE_QUAD_SUPPORT +# if ! HAVE_STRTOLL && HAVE_LONG_LONG +long long strtoll(const char *, char **, int); +# if ! defined(QUAD_MIN) +# define QUAD_MIN (-0x7fffffffffffffffL-1) +# endif +# if ! defined(QUAD_MAX) +# define QUAD_MAX (0x7fffffffffffffffL) +# endif +# endif +#else /* ! HAVE_QUAD_SUPPORT */ +# define NO_LONG_LONG 1 +#endif /* ! HAVE_QUAD_SUPPORT */ + +#if ! HAVE_TIMEGM +time_t timegm(struct tm *); +#endif + +#if ! HAVE_HSTRERROR +char *strerror(int); +#endif + +#if ! HAVE_STRLCAT +size_t strlcat(char *, const char *, size_t); +#endif + +#if ! HAVE_STRLCPY +size_t strlcpy(char *, const char *, size_t); +#endif + +#if ! HAVE_STRSEP +char *strsep(char **stringp, const char *delim); +#endif + +#if ! HAVE_MEMMOVE +# define memmove(a,b,c) bcopy((b),(a),(c)) + /* XXX: add others #defines for borken systems? */ +#endif + +#if HAVE_GETPASSPHRASE +# define getpass getpassphrase +#endif + +#if ! defined(MIN) +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#if ! defined(MAX) +# define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif + +#if ! defined(timersub) +# define timersub(tvp, uvp, vvp) \ + do { \ + (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ + (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ + if ((vvp)->tv_usec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_usec += 1000000; \ + } \ + } while (0) +#endif + +#if ! defined(S_ISLNK) +# define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK) +#endif + +#define EPOCH_YEAR 1970 +#define SECSPERHOUR 3600 +#define SECSPERDAY 86400 +#define TM_YEAR_BASE 1900 diff --git a/contrib/tnftp/src/Makefile b/contrib/tnftp/src/Makefile new file mode 100644 index 0000000..79cc5a6 --- /dev/null +++ b/contrib/tnftp/src/Makefile @@ -0,0 +1,28 @@ +# $NetBSD: Makefile,v 1.30 2005/02/11 15:13:28 jmc Exp $ +# from: @(#)Makefile 8.2 (Berkeley) 4/3/94 + +.include <bsd.own.mk> + +PROG= ftp +SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \ + progressbar.c ruserpass.c util.c + +# Uncomment the following to provide defaults for gate-ftp operation +# +#CPPFLAGS+=-DGATE_SERVER=\"ftp-gw.host\" # -DGATE_PORT=21 + +.if defined(SMALLPROG) +CPPFLAGS+=-DNO_EDITCOMPLETE -DNO_ABOUT -DNO_AUTH -DNO_HELP -DNO_STATUS +.else +LDADD+= -ledit -ltermcap +DPADD+= ${LIBEDIT} ${LIBTERMCAP} +.endif + +.if (!defined(SMALLPROG) || defined(SMALLPROG_INET6)) && (${USE_INET6} != "no") +CPPFLAGS+= -DINET6 +.endif + +cmds.o fetch.o: version.h +main.o: ftp_var.h + +.include <bsd.prog.mk> diff --git a/contrib/tnftp/src/Makefile.in b/contrib/tnftp/src/Makefile.in new file mode 100644 index 0000000..bb60f10 --- /dev/null +++ b/contrib/tnftp/src/Makefile.in @@ -0,0 +1,43 @@ +# +# $Id: Makefile.in,v 1.8 2000/08/08 07:04:27 lukem Exp $ +# + +srcdir = @srcdir@ +VPATH = @srcdir@ +SHELL = /bin/sh + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +mandir = @mandir@ +transform = @program_transform_name@ + +mandircat1 = ${mandir}/cat1 + +CC = @CC@ +CFLAGS = -I${srcdir} -I${srcdir}/.. -I. -I.. @INCLUDES@ @CFLAGS@ +LIBS = @LIBS@ +LDFLAGS = @LDFLAGS@ + +INSTALL = @INSTALL@ + +PROG = ftp +OBJS = cmds.o cmdtab.o complete.o domacro.o fetch.o ftp.o main.o \ + ruserpass.o util.o + +all: ${PROG} + +install: all + -mkdir -p ${bindir} + ${INSTALL} -m 555 ${PROG} ${bindir}/`echo ${PROG}|sed '$(transform)'` + -mkdir -p ${mandircat1} + ${INSTALL} -m 444 ${srcdir}/${PROG}.cat1 ${mandircat1}/`echo ${PROG}|sed '$(transform)'`.1 + +${PROG}: ${OBJS} @LIBDEPENDS@ + ${CC} ${CFLAGS} ${LDFLAGS} -o ${PROG} ${OBJS} ${LIBS} + +clean: + rm -f core ${PROG} ${OBJS} + +distclean: clean + rm -f Makefile diff --git a/contrib/tnftp/src/cmds.c b/contrib/tnftp/src/cmds.c new file mode 100644 index 0000000..69dbd18 --- /dev/null +++ b/contrib/tnftp/src/cmds.c @@ -0,0 +1,2753 @@ +/* $NetBSD: cmds.c,v 1.112 2005/04/11 01:49:31 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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. + */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94"; +#else +__RCSID("$NetBSD: cmds.c,v 1.112 2005/04/11 01:49:31 lukem Exp $"); +#endif +#endif /* not lint */ + +/* + * FTP User Program -- Command Routines. + */ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <arpa/ftp.h> + +#include <ctype.h> +#include <err.h> +#include <glob.h> +#include <limits.h> +#include <netdb.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <libutil.h> + +#include "ftp_var.h" +#include "version.h" + +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 } +}; + +sigjmp_buf jabort; +const char *mname; + +static int confirm(const char *, const char *); + +static const char *doprocess(char *, size_t, const char *, int, int, int); +static const char *domap(char *, size_t, const char *); +static const char *docase(char *, size_t, const char *); +static const char *dotrans(char *, size_t, const char *); + +static int +confirm(const char *cmd, const char *file) +{ + char line[BUFSIZ]; + + if (!interactive || confirmrest) + return (1); + while (1) { + fprintf(ttyout, "%s %s [anpqy?]? ", cmd, file); + (void)fflush(ttyout); + if (fgets(line, sizeof(line), stdin) == NULL) { + mflag = 0; + fprintf(ttyout, "\nEOF received; %s aborted\n", mname); + clearerr(stdin); + return (0); + } + switch (tolower((unsigned char)*line)) { + case 'a': + confirmrest = 1; + fprintf(ttyout, + "Prompting off for duration of %s.\n", cmd); + break; + case 'p': + interactive = 0; + fputs("Interactive mode: off.\n", ttyout); + break; + case 'q': + mflag = 0; + fprintf(ttyout, "%s aborted.\n", mname); + /* FALLTHROUGH */ + case 'n': + return (0); + case '?': + fprintf(ttyout, + " confirmation options:\n" + "\ta answer `yes' for the duration of %s\n" + "\tn answer `no' for this file\n" + "\tp turn off `prompt' mode\n" + "\tq stop the current %s\n" + "\ty answer `yes' for this file\n" + "\t? this help list\n", + cmd, cmd); + continue; /* back to while(1) */ + } + return (1); + } + /* NOTREACHED */ +} + +/* + * Set transfer type. + */ +void +settype(int argc, char *argv[]) +{ + struct types *p; + int comret; + + if (argc == 0 || argc > 2) { + char *sep; + + fprintf(ttyout, "usage: %s [", argv[0]); + sep = " "; + for (p = types; p->t_name; p++) { + fprintf(ttyout, "%s%s", sep, p->t_name); + sep = " | "; + } + fputs(" ]\n", ttyout); + code = -1; + return; + } + if (argc < 2) { + fprintf(ttyout, "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) { + fprintf(ttyout, "%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) { + (void)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) { + warnx("internal error: unknown type %d.", 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[]) +{ + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + stype[1] = "binary"; + settype(2, stype); +} + +/* + * Set ascii transfer type. + */ +/*VARARGS*/ +void +setascii(int argc, char *argv[]) +{ + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + stype[1] = "ascii"; + settype(2, stype); +} + +/* + * Set tenex transfer type. + */ +/*VARARGS*/ +void +settenex(int argc, char *argv[]) +{ + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + stype[1] = "tenex"; + settype(2, stype); +} + +/* + * Set file transfer mode. + */ +/*ARGSUSED*/ +void +setftmode(int argc, char *argv[]) +{ + + if (argc != 2) { + fprintf(ttyout, "usage: %s mode-name\n", argv[0]); + code = -1; + return; + } + fprintf(ttyout, "We only support %s mode, sorry.\n", modename); + code = -1; +} + +/* + * Set file transfer format. + */ +/*ARGSUSED*/ +void +setform(int argc, char *argv[]) +{ + + if (argc != 2) { + fprintf(ttyout, "usage: %s format\n", argv[0]); + code = -1; + return; + } + fprintf(ttyout, "We only support %s format, sorry.\n", formname); + code = -1; +} + +/* + * Set file transfer structure. + */ +/*ARGSUSED*/ +void +setstruct(int argc, char *argv[]) +{ + + if (argc != 2) { + fprintf(ttyout, "usage: %s struct-mode\n", argv[0]); + code = -1; + return; + } + fprintf(ttyout, "We only support %s structure, sorry.\n", structname); + code = -1; +} + +/* + * Send a single file. + */ +void +put(int argc, char *argv[]) +{ + char buf[MAXPATHLEN]; + char *cmd; + int loc = 0; + char *locfile; + const char *remfile; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "local-file"))) + goto usage; + if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) { + usage: + fprintf(ttyout, "usage: %s local-file [remote-file]\n", + argv[0]); + code = -1; + return; + } + if ((locfile = globulize(argv[1])) == NULL) { + code = -1; + return; + } + remfile = argv[2]; + if (loc) /* If argv[2] is a copy of the old argv[1], update it */ + remfile = locfile; + cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); + remfile = doprocess(buf, sizeof(buf), remfile, + 0, loc && ntflag, loc && mapflag); + sendrequest(cmd, locfile, remfile, + locfile != argv[1] || remfile != argv[2]); + free(locfile); +} + +static const char * +doprocess(char *dst, size_t dlen, const char *src, + int casef, int transf, int mapf) +{ + if (casef) + src = docase(dst, dlen, src); + if (transf) + src = dotrans(dst, dlen, src); + if (mapf) + src = domap(dst, dlen, src); + return src; +} + +/* + * Send multiple files. + */ +void +mput(int argc, char *argv[]) +{ + int i; + sigfunc oldintr; + int ointer; + const char *tp; + + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "local-files"))) { + fprintf(ttyout, "usage: %s local-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = xsignal(SIGINT, mintr); + if (sigsetjmp(jabort, 1)) + mabort(); + if (proxy) { + char *cp; + + while ((cp = remglob(argv, 0, NULL)) != NULL) { + if (*cp == '\0' || !connected) { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + char buf[MAXPATHLEN]; + tp = doprocess(buf, sizeof(buf), cp, + mcase, ntflag, mapflag); + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, cp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mput")) { + mflag++; + } + interactive = ointer; + } + } + } + goto cleanupmput; + } + for (i = 1; i < argc && connected; i++) { + char **cpp; + glob_t gl; + int flags; + + if (!doglob) { + if (mflag && confirm(argv[0], argv[i])) { + char buf[MAXPATHLEN]; + tp = doprocess(buf, sizeof(buf), argv[i], + 0, ntflag, mapflag); + sendrequest((sunique) ? "STOU" : "STOR", + argv[i], tp, tp != argv[i] || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mput")) { + mflag++; + } + interactive = ointer; + } + } + continue; + } + + memset(&gl, 0, sizeof(gl)); + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; + if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { + warnx("%s: not found", argv[i]); + globfree(&gl); + continue; + } + for (cpp = gl.gl_pathv; cpp && *cpp != NULL && connected; + cpp++) { + if (mflag && confirm(argv[0], *cpp)) { + char buf[MAXPATHLEN]; + tp = *cpp; + tp = doprocess(buf, sizeof(buf), *cpp, + 0, ntflag, mapflag); + sendrequest((sunique) ? "STOU" : "STOR", + *cpp, tp, *cpp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mput")) { + mflag++; + } + interactive = ointer; + } + } + } + globfree(&gl); + } + cleanupmput: + (void)xsignal(SIGINT, oldintr); + mflag = 0; +} + +void +reget(int argc, char *argv[]) +{ + + (void)getit(argc, argv, 1, "r+"); +} + +void +get(int argc, char *argv[]) +{ + + (void)getit(argc, argv, 0, restart_point ? "r+" : "w" ); +} + +/* + * Receive one file. + * If restartit is 1, restart the xfer always. + * If restartit is -1, restart the xfer only if the remote file is newer. + */ +int +getit(int argc, char *argv[], int restartit, const char *mode) +{ + int loc, rval; + char *remfile, *olocfile; + const char *locfile; + char buf[MAXPATHLEN]; + + loc = rval = 0; + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "remote-file"))) + goto usage; + if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) { + usage: + fprintf(ttyout, "usage: %s remote-file [local-file]\n", + argv[0]); + code = -1; + return (0); + } + remfile = argv[1]; + if ((olocfile = globulize(argv[2])) == NULL) { + code = -1; + return (0); + } + locfile = doprocess(buf, sizeof(buf), olocfile, + loc && mcase, loc && ntflag, loc && mapflag); + if (restartit) { + struct stat stbuf; + int ret; + + if (! features[FEAT_REST_STREAM]) { + fprintf(ttyout, + "Restart is not supported by the remote server.\n"); + return (0); + } + ret = stat(locfile, &stbuf); + if (restartit == 1) { + if (ret < 0) { + warn("local: %s", locfile); + goto freegetit; + } + restart_point = stbuf.st_size; + } else { + if (ret == 0) { + time_t mtime; + + mtime = remotemodtime(argv[1], 0); + if (mtime == -1) + goto freegetit; + if (stbuf.st_mtime >= mtime) { + rval = 1; + goto freegetit; + } + } + } + } + + recvrequest("RETR", locfile, remfile, mode, + remfile != argv[1] || locfile != argv[2], loc); + restart_point = 0; + freegetit: + (void)free(olocfile); + return (rval); +} + +/* ARGSUSED */ +void +mintr(int signo) +{ + + alarmtimer(0); + if (fromatty) + write(fileno(ttyout), "\n", 1); + siglongjmp(jabort, 1); +} + +void +mabort(void) +{ + int ointer, oconf; + + if (mflag && fromatty) { + ointer = interactive; + oconf = confirmrest; + interactive = 1; + confirmrest = 0; + if (confirm("Continue with", mname)) { + interactive = ointer; + confirmrest = oconf; + return; + } + interactive = ointer; + confirmrest = oconf; + } + mflag = 0; +} + +/* + * Get multiple files. + */ +void +mget(int argc, char *argv[]) +{ + sigfunc oldintr; + int ointer; + char *cp; + const char *tp; + int restartit; + + if (argc == 0 || + (argc == 1 && !another(&argc, &argv, "remote-files"))) { + fprintf(ttyout, "usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + restart_point = 0; + restartit = 0; + if (strcmp(argv[0], "mreget") == 0) { + if (! features[FEAT_REST_STREAM]) { + fprintf(ttyout, + "Restart is not supported by the remote server.\n"); + return; + } + restartit = 1; + } + oldintr = xsignal(SIGINT, mintr); + if (sigsetjmp(jabort, 1)) + mabort(); + while ((cp = remglob(argv, proxy, NULL)) != NULL) { + char buf[MAXPATHLEN]; + if (*cp == '\0' || !connected) { + mflag = 0; + continue; + } + if (! mflag) + continue; + if (! fileindir(cp, localcwd)) { + fprintf(ttyout, "Skipping non-relative filename `%s'\n", + cp); + continue; + } + if (!confirm(argv[0], cp)) + continue; + tp = doprocess(buf, sizeof(buf), cp, mcase, ntflag, mapflag); + if (restartit) { + struct stat stbuf; + + if (stat(tp, &stbuf) == 0) + restart_point = stbuf.st_size; + else + warn("stat %s", tp); + } + recvrequest("RETR", tp, cp, restart_point ? "r+" : "w", + tp != cp || !interactive, 1); + restart_point = 0; + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mget")) + mflag++; + interactive = ointer; + } + } + (void)xsignal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Read list of filenames from a local file and get those + */ +void +fget(int argc, char *argv[]) +{ + char *buf, *mode; + FILE *fp; + + if (argc != 2) { + fprintf(ttyout, "usage: %s localfile\n", argv[0]); + code = -1; + return; + } + + fp = fopen(argv[1], "r"); + if (fp == NULL) { + fprintf(ttyout, "Cannot open source file %s\n", argv[1]); + code = -1; + return; + } + + argv[0] = "get"; + mode = restart_point ? "r+" : "w"; + + for (; + (buf = fparseln(fp, NULL, NULL, "\0\0\0", 0)) != NULL; + free(buf)) { + if (buf[0] == '\0') + continue; + argv[1] = buf; + (void)getit(argc, argv, 0, mode); + } + fclose(fp); +} + +char * +onoff(int bool) +{ + + return (bool ? "on" : "off"); +} + +/* + * Show status. + */ +/*ARGSUSED*/ +void +status(int argc, char *argv[]) +{ + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } +#ifndef NO_STATUS + if (connected) + fprintf(ttyout, "Connected %sto %s.\n", + connected == -1 ? "and logged in" : "", hostname); + else + fputs("Not connected.\n", ttyout); + if (!proxy) { + pswitch(1); + if (connected) { + fprintf(ttyout, "Connected for proxy commands to %s.\n", + hostname); + } + else { + fputs("No proxy connection.\n", ttyout); + } + pswitch(0); + } + fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode), + *gateserver ? gateserver : "(none)", gateport); + fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n", + onoff(passivemode), onoff(activefallback)); + fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n", + modename, typename, formname, structname); + fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n", + onoff(verbose), onoff(bell), onoff(interactive), onoff(doglob)); + fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n", + onoff(sunique), onoff(runique)); + fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve)); + fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase), + onoff(crflag)); + if (ntflag) { + fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout); + } + else { + fputs("Ntrans: off.\n", ttyout); + } + if (mapflag) { + fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout); + } + else { + fputs("Nmap: off.\n", ttyout); + } + fprintf(ttyout, + "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n", + onoff(hash), mark, onoff(progress)); + fprintf(ttyout, + "Get transfer rate throttle: %s; maximum: %d; increment %d.\n", + onoff(rate_get), rate_get, rate_get_incr); + fprintf(ttyout, + "Put transfer rate throttle: %s; maximum: %d; increment %d.\n", + onoff(rate_put), rate_put, rate_put_incr); + fprintf(ttyout, + "Socket buffer sizes: send %d, receive %d.\n", + sndbuf_size, rcvbuf_size); + fprintf(ttyout, "Use of PORT cmds: %s.\n", onoff(sendport)); + fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4), + epsv4bad ? " (disabled for this connection)" : ""); + fprintf(ttyout, "Command line editing: %s.\n", +#ifdef NO_EDITCOMPLETE + "support not compiled in" +#else /* !def NO_EDITCOMPLETE */ + onoff(editing) +#endif /* !def NO_EDITCOMPLETE */ + ); + if (macnum > 0) { + int i; + + fputs("Macros:\n", ttyout); + for (i=0; i<macnum; i++) { + fprintf(ttyout, "\t%s\n", macros[i].mac_name); + } + } +#endif /* !def NO_STATUS */ + fprintf(ttyout, "Version: %s %s\n", FTP_PRODUCT, FTP_VERSION); + code = 0; +} + +/* + * Toggle a variable + */ +int +togglevar(int argc, char *argv[], int *var, const char *mesg) +{ + if (argc == 1) { + *var = !*var; + } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) { + *var = 1; + } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) { + *var = 0; + } else { + fprintf(ttyout, "usage: %s [ on | off ]\n", argv[0]); + return (-1); + } + if (mesg) + fprintf(ttyout, "%s %s.\n", mesg, onoff(*var)); + return (*var); +} + +/* + * Set beep on cmd completed mode. + */ +/*VARARGS*/ +void +setbell(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &bell, "Bell mode"); +} + +/* + * Set command line editing + */ +/*VARARGS*/ +void +setedit(int argc, char *argv[]) +{ + +#ifdef NO_EDITCOMPLETE + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + if (verbose) + fputs("Editing support not compiled in; ignoring command.\n", + ttyout); +#else /* !def NO_EDITCOMPLETE */ + code = togglevar(argc, argv, &editing, "Editing mode"); + controlediting(); +#endif /* !def NO_EDITCOMPLETE */ +} + +/* + * Turn on packet tracing. + */ +/*VARARGS*/ +void +settrace(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &trace, "Packet tracing"); +} + +/* + * Toggle hash mark printing during transfers, or set hash mark bytecount. + */ +/*VARARGS*/ +void +sethash(int argc, char *argv[]) +{ + if (argc == 1) + hash = !hash; + else if (argc != 2) { + fprintf(ttyout, "usage: %s [ on | off | bytecount ]\n", + argv[0]); + code = -1; + return; + } else if (strcasecmp(argv[1], "on") == 0) + hash = 1; + else if (strcasecmp(argv[1], "off") == 0) + hash = 0; + else { + int nmark; + + nmark = strsuftoi(argv[1]); + if (nmark < 1) { + fprintf(ttyout, "mark: bad bytecount value `%s'.\n", + argv[1]); + code = -1; + return; + } + mark = nmark; + hash = 1; + } + fprintf(ttyout, "Hash mark printing %s", onoff(hash)); + if (hash) + fprintf(ttyout, " (%d bytes/hash mark)", mark); + fputs(".\n", ttyout); + if (hash) + progress = 0; + code = hash; +} + +/* + * Turn on printing of server echo's. + */ +/*VARARGS*/ +void +setverbose(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &verbose, "Verbose mode"); +} + +/* + * Toggle PORT/LPRT cmd use before each data connection. + */ +/*VARARGS*/ +void +setport(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds"); +} + +/* + * Toggle transfer progress bar. + */ +/*VARARGS*/ +void +setprogress(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &progress, "Progress bar"); + if (progress) + hash = 0; +} + +/* + * Turn on interactive prompting during mget, mput, and mdelete. + */ +/*VARARGS*/ +void +setprompt(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &interactive, "Interactive mode"); +} + +/* + * Toggle gate-ftp mode, or set gate-ftp server + */ +/*VARARGS*/ +void +setgate(int argc, char *argv[]) +{ + static char gsbuf[MAXHOSTNAMELEN]; + + if (argc == 0 || argc > 3) { + fprintf(ttyout, + "usage: %s [ on | off | gateserver [port] ]\n", argv[0]); + code = -1; + return; + } else if (argc < 2) { + gatemode = !gatemode; + } else { + if (argc == 2 && strcasecmp(argv[1], "on") == 0) + gatemode = 1; + else if (argc == 2 && strcasecmp(argv[1], "off") == 0) + gatemode = 0; + else { + if (argc == 3) + gateport = xstrdup(argv[2]); + (void)strlcpy(gsbuf, argv[1], sizeof(gsbuf)); + gateserver = gsbuf; + gatemode = 1; + } + } + if (gatemode && (gateserver == NULL || *gateserver == '\0')) { + fprintf(ttyout, + "Disabling gate-ftp mode - no gate-ftp server defined.\n"); + gatemode = 0; + } else { + fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", + onoff(gatemode), *gateserver ? gateserver : "(none)", + gateport); + } + code = gatemode; +} + +/* + * Toggle metacharacter interpretation on local file names. + */ +/*VARARGS*/ +void +setglob(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &doglob, "Globbing"); +} + +/* + * Toggle preserving modification times on retrieved files. + */ +/*VARARGS*/ +void +setpreserve(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &preserve, "Preserve modification times"); +} + +/* + * Set debugging mode on/off and/or set level of debugging. + */ +/*VARARGS*/ +void +setdebug(int argc, char *argv[]) +{ + if (argc == 0 || argc > 2) { + fprintf(ttyout, "usage: %s [ on | off | debuglevel ]\n", + argv[0]); + code = -1; + return; + } else if (argc == 2) { + if (strcasecmp(argv[1], "on") == 0) + debug = 1; + else if (strcasecmp(argv[1], "off") == 0) + debug = 0; + else { + int val; + + val = strsuftoi(argv[1]); + if (val < 0) { + fprintf(ttyout, "%s: bad debugging value.\n", + argv[1]); + code = -1; + return; + } + debug = val; + } + } else + debug = !debug; + if (debug) + options |= SO_DEBUG; + else + options &= ~SO_DEBUG; + fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug); + code = debug > 0; +} + +/* + * Set current working directory on remote machine. + */ +void +cd(int argc, char *argv[]) +{ + int r; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "remote-directory"))) { + fprintf(ttyout, "usage: %s remote-directory\n", argv[0]); + code = -1; + return; + } + r = command("CWD %s", argv[1]); + if (r == ERROR && code == 500) { + if (verbose) + fputs("CWD command not recognized, trying XCWD.\n", + ttyout); + r = command("XCWD %s", argv[1]); + } + if (r == COMPLETE) { + dirchange = 1; + updateremotecwd(); + } +} + +/* + * Set current working directory on local machine. + */ +void +lcd(int argc, char *argv[]) +{ + char *locdir; + + code = -1; + if (argc == 1) { + argc++; + argv[1] = localhome; + } + if (argc != 2) { + fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]); + return; + } + if ((locdir = globulize(argv[1])) == NULL) + return; + if (chdir(locdir) == -1) + warn("lcd %s", locdir); + else { + updatelocalcwd(); + if (localcwd[0]) { + fprintf(ttyout, "Local directory now: %s\n", localcwd); + code = 0; + } else { + fprintf(ttyout, "Unable to determine local directory\n"); + } + } + (void)free(locdir); +} + +/* + * Delete a single file. + */ +void +delete(int argc, char *argv[]) +{ + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "remote-file"))) { + fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + if (command("DELE %s", argv[1]) == COMPLETE) + dirchange = 1; +} + +/* + * Delete multiple files. + */ +void +mdelete(int argc, char *argv[]) +{ + sigfunc oldintr; + int ointer; + char *cp; + + if (argc == 0 || + (argc == 1 && !another(&argc, &argv, "remote-files"))) { + fprintf(ttyout, "usage: %s [remote-files]\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = xsignal(SIGINT, mintr); + if (sigsetjmp(jabort, 1)) + mabort(); + while ((cp = remglob(argv, 0, NULL)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + if (command("DELE %s", cp) == COMPLETE) + dirchange = 1; + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mdelete")) { + mflag++; + } + interactive = ointer; + } + } + } + (void)xsignal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Rename a remote file. + */ +void +renamefile(int argc, char *argv[]) +{ + + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "from-name"))) + goto usage; + if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) { + usage: + fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]); + code = -1; + return; + } + if (command("RNFR %s", argv[1]) == CONTINUE && + command("RNTO %s", argv[2]) == COMPLETE) + dirchange = 1; +} + +/* + * Get a directory listing of remote files. + * Supports being invoked as: + * cmd runs + * --- ---- + * dir, ls LIST + * mlsd MLSD + * nlist NLST + * pdir, pls LIST |$PAGER + * mmlsd MLSD |$PAGER + */ +void +ls(int argc, char *argv[]) +{ + const char *cmd; + char *remdir, *locfile; + int freelocfile, pagecmd, mlsdcmd; + + remdir = NULL; + locfile = "-"; + freelocfile = pagecmd = mlsdcmd = 0; + /* + * the only commands that start with `p' are + * the `pager' versions. + */ + if (argv[0][0] == 'p') + pagecmd = 1; + if (strcmp(argv[0] + pagecmd , "mlsd") == 0) { + if (! features[FEAT_MLST]) { + fprintf(ttyout, + "MLSD is not supported by the remote server.\n"); + return; + } + mlsdcmd = 1; + } + if (argc == 0) + goto usage; + + if (mlsdcmd) + cmd = "MLSD"; + else if (strcmp(argv[0] + pagecmd, "nlist") == 0) + cmd = "NLST"; + else + cmd = "LIST"; + + if (argc > 1) + remdir = argv[1]; + if (argc > 2) + locfile = argv[2]; + if (argc > 3 || ((pagecmd | mlsdcmd) && argc > 2)) { + usage: + if (pagecmd || mlsdcmd) + fprintf(ttyout, + "usage: %s [remote-path]\n", argv[0]); + else + fprintf(ttyout, + "usage: %s [remote-path [local-file]]\n", + argv[0]); + code = -1; + goto freels; + } + + if (pagecmd) { + char *p; + int len; + + p = getoptionvalue("pager"); + if (EMPTYSTRING(p)) + p = DEFAULTPAGER; + len = strlen(p) + 2; + locfile = xmalloc(len); + locfile[0] = '|'; + (void)strlcpy(locfile + 1, p, len - 1); + freelocfile = 1; + } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') { + mname = argv[0]; + if ((locfile = globulize(locfile)) == NULL || + !confirm("output to local-file:", locfile)) { + code = -1; + goto freels; + } + freelocfile = 1; + } + recvrequest(cmd, locfile, remdir, "w", 0, 0); + freels: + if (freelocfile && locfile) + (void)free(locfile); +} + +/* + * Get a directory listing of multiple remote files. + */ +void +mls(int argc, char *argv[]) +{ + sigfunc oldintr; + int ointer, i; + int dolist; + char *mode, *dest, *odest; + + if (argc == 0) + goto usage; + if (argc < 2 && !another(&argc, &argv, "remote-files")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "local-file")) { + usage: + fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]); + code = -1; + return; + } + odest = dest = argv[argc - 1]; + argv[argc - 1] = NULL; + mname = argv[0]; + if (strcmp(dest, "-") && *dest != '|') + if (((dest = globulize(dest)) == NULL) || + !confirm("output to local-file:", dest)) { + code = -1; + return; + } + dolist = strcmp(argv[0], "mls"); + mflag = 1; + oldintr = xsignal(SIGINT, mintr); + if (sigsetjmp(jabort, 1)) + mabort(); + for (i = 1; mflag && i < argc-1 && connected; i++) { + mode = (i == 1) ? "w" : "a"; + recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], mode, + 0, 0); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", argv[0])) { + mflag++; + } + interactive = ointer; + } + } + (void)xsignal(SIGINT, oldintr); + mflag = 0; + if (dest != odest) /* free up after globulize() */ + free(dest); +} + +/* + * Do a shell escape + */ +/*ARGSUSED*/ +void +shell(int argc, char *argv[]) +{ + pid_t pid; + sigfunc oldintr; + char shellnam[MAXPATHLEN], *shell, *namep; + int wait_status; + + if (argc == 0) { + fprintf(ttyout, "usage: %s [command [args]]\n", argv[0]); + code = -1; + return; + } + oldintr = xsignal(SIGINT, SIG_IGN); + if ((pid = fork()) == 0) { + for (pid = 3; pid < 20; pid++) + (void)close(pid); + (void)xsignal(SIGINT, SIG_DFL); + shell = getenv("SHELL"); + if (shell == NULL) + shell = _PATH_BSHELL; + namep = strrchr(shell, '/'); + if (namep == NULL) + namep = shell; + else + namep++; + (void)strlcpy(shellnam, namep, sizeof(shellnam)); + if (debug) { + fputs(shell, ttyout); + putc('\n', ttyout); + } + 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 (wait(&wait_status) != pid) + ; + (void)xsignal(SIGINT, oldintr); + if (pid == -1) { + warn("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; + + if (argc == 0) + goto usage; + if (argc < 2) + (void)another(&argc, &argv, "username"); + if (argc < 2 || argc > 4) { + usage: + fprintf(ttyout, "usage: %s username [password [account]]\n", + argv[0]); + code = -1; + return; + } + n = command("USER %s", argv[1]); + if (n == CONTINUE) { + if (argc < 3) { + argv[2] = getpass("Password: "); + argc++; + } + n = command("PASS %s", argv[2]); + } + if (n == CONTINUE) { + if (argc < 4) { + (void)fputs("Account: ", ttyout); + (void)fflush(ttyout); + if (fgets(acct, sizeof(acct) - 1, stdin) == NULL) { + fprintf(ttyout, + "\nEOF received; login aborted.\n"); + clearerr(stdin); + code = -1; + return; + } + acct[strlen(acct) - 1] = '\0'; + argv[3] = acct; argc++; + } + n = command("ACCT %s", argv[3]); + aflag++; + } + if (n != COMPLETE) { + fputs("Login failed.\n", ttyout); + return; + } + if (!aflag && argc == 4) { + (void)command("ACCT %s", argv[3]); + } + connected = -1; + getremoteinfo(); +} + +/* + * Print working directory on remote machine. + */ +/*VARARGS*/ +void +pwd(int argc, char *argv[]) +{ + + code = -1; + if (argc != 1) { + fprintf(ttyout, "usage: %s\n", argv[0]); + return; + } + if (! remotecwd[0]) + updateremotecwd(); + if (! remotecwd[0]) + fprintf(ttyout, "Unable to determine remote directory\n"); + else { + fprintf(ttyout, "Remote directory: %s\n", remotecwd); + code = 0; + } +} + +/* + * Print working directory on local machine. + */ +void +lpwd(int argc, char *argv[]) +{ + + code = -1; + if (argc != 1) { + fprintf(ttyout, "usage: %s\n", argv[0]); + return; + } + if (! localcwd[0]) + updatelocalcwd(); + if (! localcwd[0]) + fprintf(ttyout, "Unable to determine local directory\n"); + else { + fprintf(ttyout, "Local directory: %s\n", localcwd); + code = 0; + } +} + +/* + * Make a directory. + */ +void +makedir(int argc, char *argv[]) +{ + int r; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "directory-name"))) { + fprintf(ttyout, "usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + r = command("MKD %s", argv[1]); + if (r == ERROR && code == 500) { + if (verbose) + fputs("MKD command not recognized, trying XMKD.\n", + ttyout); + r = command("XMKD %s", argv[1]); + } + if (r == COMPLETE) + dirchange = 1; +} + +/* + * Remove a directory. + */ +void +removedir(int argc, char *argv[]) +{ + int r; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "directory-name"))) { + fprintf(ttyout, "usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + r = command("RMD %s", argv[1]); + if (r == ERROR && code == 500) { + if (verbose) + fputs("RMD command not recognized, trying XRMD.\n", + ttyout); + r = command("XRMD %s", argv[1]); + } + if (r == COMPLETE) + dirchange = 1; +} + +/* + * Send a line, verbatim, to the remote machine. + */ +void +quote(int argc, char *argv[]) +{ + + if (argc == 0 || + (argc == 1 && !another(&argc, &argv, "command line to send"))) { + fprintf(ttyout, "usage: %s line-to-send\n", argv[0]); + 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 == 0 || + (argc == 1 && !another(&argc, &argv, "arguments to SITE command"))){ + fprintf(ttyout, "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(const char *initial, int argc, char *argv[]) +{ + int i; + char buf[BUFSIZ]; /* must be >= sizeof(line) */ + + (void)strlcpy(buf, initial, sizeof(buf)); + for (i = 1; i < argc; i++) { + (void)strlcat(buf, argv[i], sizeof(buf)); + if (i < (argc - 1)) + (void)strlcat(buf, " ", sizeof(buf)); + } + if (command("%s", buf) == PRELIM) { + while (getreply(0) == PRELIM) + continue; + } + dirchange = 1; +} + +void +do_chmod(int argc, char *argv[]) +{ + + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "mode"))) + goto usage; + if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) { + usage: + fprintf(ttyout, "usage: %s mode remote-file\n", argv[0]); + code = -1; + return; + } + (void)command("SITE CHMOD %s %s", argv[1], argv[2]); +} + +#define COMMAND_1ARG(argc, argv, cmd) \ + if (argc == 1) \ + command(cmd); \ + else \ + command(cmd " %s", argv[1]) + +void +do_umask(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc == 0) { + fprintf(ttyout, "usage: %s [umask]\n", argv[0]); + code = -1; + return; + } + verbose = 1; + COMMAND_1ARG(argc, argv, "SITE UMASK"); + verbose = oldverbose; +} + +void +idlecmd(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc < 1 || argc > 2) { + fprintf(ttyout, "usage: %s [seconds]\n", argv[0]); + code = -1; + return; + } + verbose = 1; + COMMAND_1ARG(argc, argv, "SITE IDLE"); + verbose = oldverbose; +} + +/* + * Ask the other side for help. + */ +void +rmthelp(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + verbose = 1; + COMMAND_1ARG(argc, argv, "HELP"); + verbose = oldverbose; +} + +/* + * Terminate session and exit. + * May be called with 0, NULL. + */ +/*VARARGS*/ +void +quit(int argc, char *argv[]) +{ + + /* this may be called with argc == 0, argv == NULL */ + if (argc == 0 && argv != NULL) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + if (connected) + disconnect(0, NULL); + pswitch(1); + if (connected) + disconnect(0, NULL); + exit(0); +} + +/* + * Terminate session, but don't exit. + * May be called with 0, NULL. + */ +void +disconnect(int argc, char *argv[]) +{ + + /* this may be called with argc == 0, argv == NULL */ + if (argc == 0 && argv != NULL) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + if (!connected) + return; + (void)command("QUIT"); + cleanuppeer(); +} + +void +account(int argc, char *argv[]) +{ + char *ap; + + if (argc == 0 || argc > 2) { + fprintf(ttyout, "usage: %s [password]\n", argv[0]); + code = -1; + return; + } + else if (argc == 2) + ap = argv[1]; + else + ap = getpass("Account:"); + (void)command("ACCT %s", ap); +} + +sigjmp_buf abortprox; + +void +proxabort(int notused) +{ + + sigint_raised = 1; + alarmtimer(0); + if (!proxy) { + pswitch(1); + } + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + siglongjmp(abortprox, 1); +} + +void +doproxy(int argc, char *argv[]) +{ + struct cmd *c; + int cmdpos; + sigfunc oldintr; + + if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) { + fprintf(ttyout, "usage: %s command\n", argv[0]); + code = -1; + return; + } + c = getcmd(argv[1]); + if (c == (struct cmd *) -1) { + fputs("?Ambiguous command.\n", ttyout); + code = -1; + return; + } + if (c == 0) { + fputs("?Invalid command.\n", ttyout); + code = -1; + return; + } + if (!c->c_proxy) { + fputs("?Invalid proxy command.\n", ttyout); + code = -1; + return; + } + if (sigsetjmp(abortprox, 1)) { + code = -1; + return; + } + oldintr = xsignal(SIGINT, proxabort); + pswitch(1); + if (c->c_conn && !connected) { + fputs("Not connected.\n", ttyout); + pswitch(0); + (void)xsignal(SIGINT, oldintr); + code = -1; + return; + } + cmdpos = strcspn(line, " \t"); + if (cmdpos > 0) /* remove leading "proxy " from input buffer */ + memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1); + argv[1] = c->c_name; + (*c->c_handler)(argc-1, argv+1); + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + (void)xsignal(SIGINT, oldintr); +} + +void +setcase(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &mcase, "Case mapping"); +} + +/* + * convert the given name to lower case if it's all upper case, into + * a static buffer which is returned to the caller + */ +static const char * +docase(char *dst, size_t dlen, const char *src) +{ + size_t i; + int dochange = 1; + + for (i = 0; src[i] != '\0' && i < dlen - 1; i++) { + dst[i] = src[i]; + if (islower((unsigned char)dst[i])) + dochange = 0; + } + dst[i] = '\0'; + + if (dochange) { + for (i = 0; dst[i] != '\0'; i++) + if (isupper((unsigned char)dst[i])) + dst[i] = tolower((unsigned char)dst[i]); + } + return dst; +} + +void +setcr(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &crflag, "Carriage Return stripping"); +} + +void +setntrans(int argc, char *argv[]) +{ + + if (argc == 0 || argc > 3) { + fprintf(ttyout, "usage: %s [inchars [outchars]]\n", argv[0]); + code = -1; + return; + } + if (argc == 1) { + ntflag = 0; + fputs("Ntrans off.\n", ttyout); + code = ntflag; + return; + } + ntflag++; + code = ntflag; + (void)strlcpy(ntin, argv[1], sizeof(ntin)); + if (argc == 2) { + ntout[0] = '\0'; + return; + } + (void)strlcpy(ntout, argv[2], sizeof(ntout)); +} + +static const char * +dotrans(char *dst, size_t dlen, const char *src) +{ + const char *cp1; + char *cp2 = dst; + size_t i, ostop; + + for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) + continue; + for (cp1 = src; *cp1; cp1++) { + int found = 0; + for (i = 0; *(ntin + i) && i < 16; i++) { + if (*cp1 == *(ntin + i)) { + found++; + if (i < ostop) { + *cp2++ = *(ntout + i); + if (cp2 - dst >= dlen - 1) + goto out; + } + break; + } + } + if (!found) { + *cp2++ = *cp1; + } + } +out: + *cp2 = '\0'; + return dst; +} + +void +setnmap(int argc, char *argv[]) +{ + char *cp; + + if (argc == 1) { + mapflag = 0; + fputs("Nmap off.\n", ttyout); + code = mapflag; + return; + } + if (argc == 0 || + (argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) { + fprintf(ttyout, "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'; + (void)strlcpy(mapin, altarg, MAXPATHLEN); + while (*++cp == ' ') + continue; + (void)strlcpy(mapout, cp, MAXPATHLEN); +} + +static const char * +domap(char *dst, size_t dlen, const char *src) +{ + const char *cp1 = src; + char *cp2 = mapin; + const 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; + } + cp2 = dst; + *cp2 = '\0'; + cp1 = mapout; + while (*cp1) { + match = 0; + switch (*cp1) { + case '\\': + if (*(cp1 + 1)) { + *cp2++ = *++cp1; + } + break; + case '[': +LOOP: + if (*++cp1 == '$' && + isdigit((unsigned char)*(cp1+1))) { + if (*++cp1 == '0') { + const char *cp3 = src; + + while (*cp3) { + *cp2++ = *cp3++; + } + match = 1; + } + else if (toks[toknum = *cp1 - '1']) { + const char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp2++ = *cp3++; + } + match = 1; + } + } + else { + while (*cp1 && *cp1 != ',' && + *cp1 != ']') { + if (*cp1 == '\\') { + cp1++; + } + else if (*cp1 == '$' && + isdigit((unsigned char)*(cp1+1))) { + if (*++cp1 == '0') { + const char *cp3 = src; + + while (*cp3) { + *cp2++ = *cp3++; + } + } + else if (toks[toknum = + *cp1 - '1']) { + const char *cp3=tp[toknum]; + + while (cp3 != + te[toknum]) { + *cp2++ = *cp3++; + } + } + } + else if (*cp1) { + *cp2++ = *cp1++; + } + } + if (!*cp1) { + fputs( + "nmap: unbalanced brackets.\n", + ttyout); + return (src); + } + match = 1; + cp1--; + } + if (match) { + while (*++cp1 && *cp1 != ']') { + if (*cp1 == '\\' && *(cp1 + 1)) { + cp1++; + } + } + if (!*cp1) { + fputs( + "nmap: unbalanced brackets.\n", + ttyout); + return (src); + } + break; + } + switch (*++cp1) { + case ',': + goto LOOP; + case ']': + break; + default: + cp1--; + goto LOOP; + } + break; + case '$': + if (isdigit((unsigned char)*(cp1 + 1))) { + if (*++cp1 == '0') { + const char *cp3 = src; + + while (*cp3) { + *cp2++ = *cp3++; + } + } + else if (toks[toknum = *cp1 - '1']) { + const char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp2++ = *cp3++; + } + } + break; + } + /* intentional drop through */ + default: + *cp2++ = *cp1; + break; + } + cp1++; + } + *cp2 = '\0'; + return *dst ? dst : src; +} + +void +setpassive(int argc, char *argv[]) +{ + + if (argc == 1) { + passivemode = !passivemode; + activefallback = passivemode; + } else if (argc != 2) { + passiveusage: + fprintf(ttyout, "usage: %s [ on | off | auto ]\n", argv[0]); + code = -1; + return; + } else if (strcasecmp(argv[1], "on") == 0) { + passivemode = 1; + activefallback = 0; + } else if (strcasecmp(argv[1], "off") == 0) { + passivemode = 0; + activefallback = 0; + } else if (strcasecmp(argv[1], "auto") == 0) { + passivemode = 1; + activefallback = 1; + } else + goto passiveusage; + fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n", + onoff(passivemode), onoff(activefallback)); + code = passivemode; +} + +void +setepsv4(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &epsv4, + verbose ? "EPSV/EPRT on IPv4" : NULL); + epsv4bad = 0; +} + +void +setsunique(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &sunique, "Store unique"); +} + +void +setrunique(int argc, char *argv[]) +{ + + code = togglevar(argc, argv, &runique, "Receive unique"); +} + +int +parserate(int argc, char *argv[], int cmdlineopt) +{ + int dir, max, incr, showonly; + sigfunc oldusr1, oldusr2; + + if (argc > 4 || (argc < (cmdlineopt ? 3 : 2))) { + usage: + if (cmdlineopt) + fprintf(ttyout, + "usage: %s (all|get|put),maximum-bytes[,increment-bytes]]\n", + argv[0]); + else + fprintf(ttyout, + "usage: %s (all|get|put) [maximum-bytes [increment-bytes]]\n", + argv[0]); + return -1; + } + dir = max = incr = showonly = 0; +#define RATE_GET 1 +#define RATE_PUT 2 +#define RATE_ALL (RATE_GET | RATE_PUT) + + if (strcasecmp(argv[1], "all") == 0) + dir = RATE_ALL; + else if (strcasecmp(argv[1], "get") == 0) + dir = RATE_GET; + else if (strcasecmp(argv[1], "put") == 0) + dir = RATE_PUT; + else + goto usage; + + if (argc >= 3) { + if ((max = strsuftoi(argv[2])) < 0) + goto usage; + } else + showonly = 1; + + if (argc == 4) { + if ((incr = strsuftoi(argv[3])) <= 0) + goto usage; + } else + incr = DEFAULTINCR; + + oldusr1 = xsignal(SIGUSR1, SIG_IGN); + oldusr2 = xsignal(SIGUSR2, SIG_IGN); + if (dir & RATE_GET) { + if (!showonly) { + rate_get = max; + rate_get_incr = incr; + } + if (!cmdlineopt || verbose) + fprintf(ttyout, + "Get transfer rate throttle: %s; maximum: %d; increment %d.\n", + onoff(rate_get), rate_get, rate_get_incr); + } + if (dir & RATE_PUT) { + if (!showonly) { + rate_put = max; + rate_put_incr = incr; + } + if (!cmdlineopt || verbose) + fprintf(ttyout, + "Put transfer rate throttle: %s; maximum: %d; increment %d.\n", + onoff(rate_put), rate_put, rate_put_incr); + } + (void)xsignal(SIGUSR1, oldusr1); + (void)xsignal(SIGUSR2, oldusr2); + return 0; +} + +void +setrate(int argc, char *argv[]) +{ + + code = parserate(argc, argv, 0); +} + +/* change directory to parent directory */ +void +cdup(int argc, char *argv[]) +{ + int r; + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + r = command("CDUP"); + if (r == ERROR && code == 500) { + if (verbose) + fputs("CDUP command not recognized, trying XCUP.\n", + ttyout); + r = command("XCUP"); + } + if (r == COMPLETE) { + dirchange = 1; + updateremotecwd(); + } +} + +/* + * Restart transfer at specific point + */ +void +restart(int argc, char *argv[]) +{ + + if (argc == 0 || argc > 2) { + fprintf(ttyout, "usage: %s [restart-point]\n", argv[0]); + code = -1; + return; + } + if (! features[FEAT_REST_STREAM]) { + fprintf(ttyout, + "Restart is not supported by the remote server.\n"); + return; + } + if (argc == 2) { + off_t rp; + char *ep; + + rp = STRTOLL(argv[1], &ep, 10); + if (rp < 0 || *ep != '\0') + fprintf(ttyout, "restart: Invalid offset `%s'\n", + argv[1]); + else + restart_point = rp; + } + if (restart_point == 0) + fputs("No restart point defined.\n", ttyout); + else + fprintf(ttyout, + "Restarting at " LLF " for next get, put or append\n", + (LLT)restart_point); +} + +/* + * Show remote system type + */ +void +syst(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + verbose = 1; /* If we aren't verbose, this doesn't do anything! */ + (void)command("SYST"); + verbose = oldverbose; +} + +void +macdef(int argc, char *argv[]) +{ + char *tmp; + int c; + + if (argc == 0) + goto usage; + if (macnum == 16) { + fputs("Limit of 16 macros have already been defined.\n", + ttyout); + code = -1; + return; + } + if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) { + usage: + fprintf(ttyout, "usage: %s macro_name\n", argv[0]); + code = -1; + return; + } + if (interactive) + fputs( + "Enter macro line by line, terminating it with a null line.\n", + ttyout); + (void)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) { + fputs("macdef: end of file encountered.\n", ttyout); + 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') { + fputs("Macro not defined - 4K buffer exceeded.\n", + ttyout); + code = -1; + return; + } + } +} + +/* + * Get size of file on remote machine + */ +void +sizecmd(int argc, char *argv[]) +{ + off_t size; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "remote-file"))) { + fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + size = remotesize(argv[1], 1); + if (size != -1) + fprintf(ttyout, + "%s\t" LLF "\n", argv[1], (LLT)size); + code = (size > 0); +} + +/* + * Get last modification time of file on remote machine + */ +void +modtime(int argc, char *argv[]) +{ + time_t mtime; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "remote-file"))) { + fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + mtime = remotemodtime(argv[1], 1); + if (mtime != -1) + fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime))); + code = (mtime > 0); +} + +/* + * Show status on remote machine + */ +void +rmtstatus(int argc, char *argv[]) +{ + + if (argc == 0) { + fprintf(ttyout, "usage: %s [remote-file]\n", argv[0]); + code = -1; + return; + } + COMMAND_1ARG(argc, argv, "STAT"); +} + +/* + * Get file if modtime is more recent than current file + */ +void +newer(int argc, char *argv[]) +{ + + if (getit(argc, argv, -1, "w")) + fprintf(ttyout, + "Local file \"%s\" is newer than remote file \"%s\".\n", + argv[2], argv[1]); +} + +/* + * Display one local file through $PAGER. + */ +void +lpage(int argc, char *argv[]) +{ + int len; + char *p, *pager, *locfile; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "local-file"))) { + fprintf(ttyout, "usage: %s local-file\n", argv[0]); + code = -1; + return; + } + if ((locfile = globulize(argv[1])) == NULL) { + code = -1; + return; + } + p = getoptionvalue("pager"); + if (EMPTYSTRING(p)) + p = DEFAULTPAGER; + len = strlen(p) + strlen(locfile) + 2; + pager = xmalloc(len); + (void)strlcpy(pager, p, len); + (void)strlcat(pager, " ", len); + (void)strlcat(pager, locfile, len); + system(pager); + code = 0; + (void)free(pager); + (void)free(locfile); +} + +/* + * Display one remote file through $PAGER. + */ +void +page(int argc, char *argv[]) +{ + int ohash, orestart_point, overbose, len; + char *p, *pager; + + if (argc == 0 || argc > 2 || + (argc == 1 && !another(&argc, &argv, "remote-file"))) { + fprintf(ttyout, "usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + p = getoptionvalue("pager"); + if (EMPTYSTRING(p)) + p = DEFAULTPAGER; + len = strlen(p) + 2; + pager = xmalloc(len); + pager[0] = '|'; + (void)strlcpy(pager + 1, p, len - 1); + + ohash = hash; + orestart_point = restart_point; + overbose = verbose; + hash = restart_point = verbose = 0; + recvrequest("RETR", pager, argv[1], "r+", 1, 0); + hash = ohash; + restart_point = orestart_point; + verbose = overbose; + (void)free(pager); +} + +/* + * Set the socket send or receive buffer size. + */ +void +setxferbuf(int argc, char *argv[]) +{ + int size, dir; + + if (argc != 2) { + usage: + fprintf(ttyout, "usage: %s size\n", argv[0]); + code = -1; + return; + } + if (strcasecmp(argv[0], "sndbuf") == 0) + dir = RATE_PUT; + else if (strcasecmp(argv[0], "rcvbuf") == 0) + dir = RATE_GET; + else if (strcasecmp(argv[0], "xferbuf") == 0) + dir = RATE_ALL; + else + goto usage; + + if ((size = strsuftoi(argv[1])) == -1) + goto usage; + + if (size == 0) { + fprintf(ttyout, "%s: size must be positive.\n", argv[0]); + goto usage; + } + + if (dir & RATE_PUT) + sndbuf_size = size; + if (dir & RATE_GET) + rcvbuf_size = size; + fprintf(ttyout, "Socket buffer sizes: send %d, receive %d.\n", + sndbuf_size, rcvbuf_size); + code = 0; +} + +/* + * Set or display options (defaults are provided by various env vars) + */ +void +setoption(int argc, char *argv[]) +{ + struct option *o; + + code = -1; + if (argc == 0 || (argc != 1 && argc != 3)) { + fprintf(ttyout, "usage: %s [option value]\n", argv[0]); + return; + } + +#define OPTIONINDENT ((int) sizeof("http_proxy")) + if (argc == 1) { + for (o = optiontab; o->name != NULL; o++) { + fprintf(ttyout, "%-*s\t%s\n", OPTIONINDENT, + o->name, o->value ? o->value : ""); + } + } else { + o = getoption(argv[1]); + if (o == NULL) { + fprintf(ttyout, "No such option `%s'.\n", argv[1]); + return; + } + FREEPTR(o->value); + o->value = xstrdup(argv[2]); + if (verbose) + fprintf(ttyout, "Setting `%s' to `%s'.\n", + o->name, o->value); + } + code = 0; +} + +/* + * Unset an option + */ +void +unsetoption(int argc, char *argv[]) +{ + struct option *o; + + code = -1; + if (argc == 0 || argc != 2) { + fprintf(ttyout, "usage: %s option\n", argv[0]); + return; + } + + o = getoption(argv[1]); + if (o == NULL) { + fprintf(ttyout, "No such option `%s'.\n", argv[1]); + return; + } + FREEPTR(o->value); + fprintf(ttyout, "Unsetting `%s'.\n", o->name); + code = 0; +} + +/* + * Display features supported by the remote host. + */ +void +feat(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc == 0) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + if (! features[FEAT_FEAT]) { + fprintf(ttyout, + "FEAT is not supported by the remote server.\n"); + return; + } + verbose = 1; /* If we aren't verbose, this doesn't do anything! */ + (void)command("FEAT"); + verbose = oldverbose; +} + +void +mlst(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc < 1 || argc > 2) { + fprintf(ttyout, "usage: %s [remote-path]\n", argv[0]); + code = -1; + return; + } + if (! features[FEAT_MLST]) { + fprintf(ttyout, + "MLST is not supported by the remote server.\n"); + return; + } + verbose = 1; /* If we aren't verbose, this doesn't do anything! */ + COMMAND_1ARG(argc, argv, "MLST"); + verbose = oldverbose; +} + +void +opts(int argc, char *argv[]) +{ + int oldverbose = verbose; + + if (argc < 2 || argc > 3) { + fprintf(ttyout, "usage: %s command [options]\n", argv[0]); + code = -1; + return; + } + if (! features[FEAT_FEAT]) { + fprintf(ttyout, + "OPTS is not supported by the remote server.\n"); + return; + } + verbose = 1; /* If we aren't verbose, this doesn't do anything! */ + if (argc == 2) + command("OPTS %s", argv[1]); + else + command("OPTS %s %s", argv[1], argv[2]); + verbose = oldverbose; +} diff --git a/contrib/tnftp/src/cmdtab.c b/contrib/tnftp/src/cmdtab.c new file mode 100644 index 0000000..04efade --- /dev/null +++ b/contrib/tnftp/src/cmdtab.c @@ -0,0 +1,309 @@ +/* $NetBSD: cmdtab.c,v 1.44 2005/04/11 01:49:31 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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 <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94"; +#else +__RCSID("$NetBSD: cmdtab.c,v 1.44 2005/04/11 01:49:31 lukem Exp $"); +#endif +#endif /* not lint */ + +#include <stdio.h> +#include "ftp_var.h" + +/* + * User FTP -- Command Tables. + */ + +#define HSTR static const char + +#ifndef NO_HELP +HSTR accounthelp[] = "send account command to remote server"; +HSTR appendhelp[] = "append to a file"; +HSTR asciihelp[] = "set ascii transfer type"; +HSTR beephelp[] = "beep when command completed"; +HSTR binaryhelp[] = "set binary transfer type"; +HSTR casehelp[] = "toggle mget upper/lower case id mapping"; +HSTR cdhelp[] = "change remote working directory"; +HSTR cduphelp[] = "change remote working directory to parent directory"; +HSTR chmodhelp[] = "change file permissions of remote file"; +HSTR connecthelp[] = "connect to remote ftp server"; +HSTR crhelp[] = "toggle carriage return stripping on ascii gets"; +HSTR debughelp[] = "toggle/set debugging mode"; +HSTR deletehelp[] = "delete remote file"; +HSTR disconhelp[] = "terminate ftp session"; +HSTR domachelp[] = "execute macro"; +HSTR edithelp[] = "toggle command line editing"; +HSTR epsv4help[] = "toggle use of EPSV/EPRT on IPv4 ftp"; +HSTR feathelp[] = "show FEATures supported by remote system"; +HSTR formhelp[] = "set file transfer format"; +HSTR gatehelp[] = "toggle gate-ftp; specify host[:port] to change proxy"; +HSTR globhelp[] = "toggle metacharacter expansion of local file names"; +HSTR hashhelp[] = "toggle printing `#' marks; specify number to set size"; +HSTR helphelp[] = "print local help information"; +HSTR idlehelp[] = "get (set) idle timer on remote side"; +HSTR lcdhelp[] = "change local working directory"; +HSTR lpagehelp[] = "view a local file through your pager"; +HSTR lpwdhelp[] = "print local working directory"; +HSTR lshelp[] = "list contents of remote path"; +HSTR macdefhelp[] = "define a macro"; +HSTR mdeletehelp[] = "delete multiple files"; +HSTR mgethelp[] = "get multiple files"; +HSTR mregethelp[] = "get multiple files restarting at end of local file"; +HSTR fgethelp[] = "get files using a localfile as a source of names"; +HSTR mkdirhelp[] = "make directory on the remote machine"; +HSTR mlshelp[] = "list contents of multiple remote directories"; +HSTR mlsdhelp[] = "list contents of remote directory in a machine " + "parsable form"; +HSTR mlsthelp[] = "list remote path in a machine parsable form"; +HSTR modehelp[] = "set file transfer mode"; +HSTR modtimehelp[] = "show last modification time of remote file"; +HSTR mputhelp[] = "send multiple files"; +HSTR newerhelp[] = "get file if remote file is newer than local file "; +HSTR nmaphelp[] = "set templates for default file name mapping"; +HSTR ntranshelp[] = "set translation table for default file name mapping"; +HSTR optshelp[] = "show or set options for remote commands"; +HSTR pagehelp[] = "view a remote file through your pager"; +HSTR passivehelp[] = "toggle use of passive transfer mode"; +HSTR plshelp[] = "list contents of remote path through your pager"; +HSTR pmlsdhelp[] = "list contents of remote directory in a machine " + "parsable form through your pager"; +HSTR porthelp[] = "toggle use of PORT/LPRT cmd for each data connection"; +HSTR preservehelp[] ="toggle preservation of modification time of " + "retrieved files"; +HSTR progresshelp[] ="toggle transfer progress meter"; +HSTR prompthelp[] = "force interactive prompting on multiple commands"; +HSTR proxyhelp[] = "issue command on alternate connection"; +HSTR pwdhelp[] = "print working directory on remote machine"; +HSTR quithelp[] = "terminate ftp session and exit"; +HSTR quotehelp[] = "send arbitrary ftp command"; +HSTR ratehelp[] = "set transfer rate limit (in bytes/second)"; +HSTR receivehelp[] = "receive file"; +HSTR regethelp[] = "get file restarting at end of local file"; +HSTR remotehelp[] = "get help from remote server"; +HSTR renamehelp[] = "rename file"; +HSTR resethelp[] = "clear queued command replies"; +HSTR restarthelp[]= "restart file transfer at bytecount"; +HSTR rmdirhelp[] = "remove directory on the remote machine"; +HSTR rmtstatushelp[]="show status of remote machine"; +HSTR runiquehelp[] = "toggle store unique for local files"; +HSTR sendhelp[] = "send one file"; +HSTR sethelp[] = "set or display options"; +HSTR shellhelp[] = "escape to the shell"; +HSTR sitehelp[] = "send site specific command to remote server\n" + "\t\tTry \"rhelp site\" or \"site help\" " + "for more information"; +HSTR sizecmdhelp[] = "show size of remote file"; +HSTR statushelp[] = "show current status"; +HSTR structhelp[] = "set file transfer structure"; +HSTR suniquehelp[] = "toggle store unique on remote machine"; +HSTR systemhelp[] = "show remote system type"; +HSTR tenexhelp[] = "set tenex file transfer type"; +HSTR tracehelp[] = "toggle packet tracing"; +HSTR typehelp[] = "set file transfer type"; +HSTR umaskhelp[] = "get (set) umask on remote side"; +HSTR unsethelp[] = "unset an option"; +HSTR usagehelp[] = "show command usage"; +HSTR userhelp[] = "send new user information"; +HSTR verbosehelp[] = "toggle verbose mode"; +HSTR xferbufhelp[] = "set socket send/receive buffer size"; +#endif + +HSTR empty[] = ""; + +#ifdef NO_HELP +#define H(x) empty +#else +#define H(x) x +#endif + +#ifdef NO_EDITCOMPLETE +#define CMPL(x) +#define CMPL0 +#else /* !NO_EDITCOMPLETE */ +#define CMPL(x) #x, +#define CMPL0 empty, +#endif /* !NO_EDITCOMPLETE */ + +struct cmd cmdtab[] = { + { "!", H(shellhelp), 0, 0, 0, CMPL0 shell }, + { "$", H(domachelp), 1, 0, 0, CMPL0 domacro }, + { "account", H(accounthelp), 0, 1, 1, CMPL0 account}, + { "append", H(appendhelp), 1, 1, 1, CMPL(lr) put }, + { "ascii", H(asciihelp), 0, 1, 1, CMPL0 setascii }, + { "bell", H(beephelp), 0, 0, 0, CMPL0 setbell }, + { "binary", H(binaryhelp), 0, 1, 1, CMPL0 setbinary }, + { "bye", H(quithelp), 0, 0, 0, CMPL0 quit }, + { "case", H(casehelp), 0, 0, 1, CMPL0 setcase }, + { "cd", H(cdhelp), 0, 1, 1, CMPL(r) cd }, + { "cdup", H(cduphelp), 0, 1, 1, CMPL0 cdup }, + { "chmod", H(chmodhelp), 0, 1, 1, CMPL(nr) do_chmod }, + { "close", H(disconhelp), 0, 1, 1, CMPL0 disconnect }, + { "cr", H(crhelp), 0, 0, 0, CMPL0 setcr }, + { "debug", H(debughelp), 0, 0, 0, CMPL0 setdebug }, + { "delete", H(deletehelp), 0, 1, 1, CMPL(r) delete }, + { "dir", H(lshelp), 1, 1, 1, CMPL(rl) ls }, + { "disconnect", H(disconhelp), 0, 1, 1, CMPL0 disconnect }, + { "edit", H(edithelp), 0, 0, 0, CMPL0 setedit }, + { "epsv4", H(epsv4help), 0, 0, 0, CMPL0 setepsv4 }, + { "exit", H(quithelp), 0, 0, 0, CMPL0 quit }, + { "features", H(feathelp), 0, 1, 1, CMPL0 feat }, + { "fget", H(fgethelp), 1, 1, 1, CMPL(l) fget }, + { "form", H(formhelp), 0, 1, 1, CMPL0 setform }, + { "ftp", H(connecthelp), 0, 0, 1, CMPL0 setpeer }, + { "gate", H(gatehelp), 0, 0, 0, CMPL0 setgate }, + { "get", H(receivehelp), 1, 1, 1, CMPL(rl) get }, + { "glob", H(globhelp), 0, 0, 0, CMPL0 setglob }, + { "hash", H(hashhelp), 0, 0, 0, CMPL0 sethash }, + { "help", H(helphelp), 0, 0, 1, CMPL(C) help }, + { "idle", H(idlehelp), 0, 1, 1, CMPL0 idlecmd }, + { "image", H(binaryhelp), 0, 1, 1, CMPL0 setbinary }, + { "lcd", H(lcdhelp), 0, 0, 0, CMPL(l) lcd }, + { "less", H(pagehelp), 1, 1, 1, CMPL(r) page }, + { "lpage", H(lpagehelp), 0, 0, 0, CMPL(l) lpage }, + { "lpwd", H(lpwdhelp), 0, 0, 0, CMPL0 lpwd }, + { "ls", H(lshelp), 1, 1, 1, CMPL(rl) ls }, + { "macdef", H(macdefhelp), 0, 0, 0, CMPL0 macdef }, + { "mdelete", H(mdeletehelp), 1, 1, 1, CMPL(R) mdelete }, + { "mdir", H(mlshelp), 1, 1, 1, CMPL(R) mls }, + { "mget", H(mgethelp), 1, 1, 1, CMPL(R) mget }, + { "mkdir", H(mkdirhelp), 0, 1, 1, CMPL(r) makedir }, + { "mls", H(mlshelp), 1, 1, 1, CMPL(R) mls }, + { "mlsd", H(mlsdhelp), 1, 1, 1, CMPL(r) ls }, + { "mlst", H(mlsthelp), 1, 1, 1, CMPL(r) mlst }, + { "mode", H(modehelp), 0, 1, 1, CMPL0 setftmode }, + { "modtime", H(modtimehelp), 0, 1, 1, CMPL(r) modtime }, + { "more", H(pagehelp), 1, 1, 1, CMPL(r) page }, + { "mput", H(mputhelp), 1, 1, 1, CMPL(L) mput }, + { "mreget", H(mregethelp), 1, 1, 1, CMPL(R) mget }, + { "msend", H(mputhelp), 1, 1, 1, CMPL(L) mput }, + { "newer", H(newerhelp), 1, 1, 1, CMPL(r) newer }, + { "nlist", H(lshelp), 1, 1, 1, CMPL(rl) ls }, + { "nmap", H(nmaphelp), 0, 0, 1, CMPL0 setnmap }, + { "ntrans", H(ntranshelp), 0, 0, 1, CMPL0 setntrans }, + { "open", H(connecthelp), 0, 0, 1, CMPL0 setpeer }, + { "page", H(pagehelp), 1, 1, 1, CMPL(r) page }, + { "passive", H(passivehelp), 0, 0, 0, CMPL0 setpassive }, + { "pdir", H(plshelp), 1, 1, 1, CMPL(r) ls }, + { "pls", H(plshelp), 1, 1, 1, CMPL(r) ls }, + { "pmlsd", H(pmlsdhelp), 1, 1, 1, CMPL(r) ls }, + { "preserve", H(preservehelp),0, 0, 0, CMPL0 setpreserve }, + { "progress", H(progresshelp),0, 0, 0, CMPL0 setprogress }, + { "prompt", H(prompthelp), 0, 0, 0, CMPL0 setprompt }, + { "proxy", H(proxyhelp), 0, 0, 1, CMPL(c) doproxy }, + { "put", H(sendhelp), 1, 1, 1, CMPL(lr) put }, + { "pwd", H(pwdhelp), 0, 1, 1, CMPL0 pwd }, + { "quit", H(quithelp), 0, 0, 0, CMPL0 quit }, + { "quote", H(quotehelp), 1, 1, 1, CMPL0 quote }, + { "rate", H(ratehelp), 0, 0, 0, CMPL0 setrate }, + { "rcvbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf }, + { "recv", H(receivehelp), 1, 1, 1, CMPL(rl) get }, + { "reget", H(regethelp), 1, 1, 1, CMPL(rl) reget }, + { "remopts", H(optshelp), 0, 1, 1, CMPL0 opts }, + { "rename", H(renamehelp), 0, 1, 1, CMPL(rr) renamefile }, + { "reset", H(resethelp), 0, 1, 1, CMPL0 reset }, + { "restart", H(restarthelp), 1, 1, 1, CMPL0 restart }, + { "rhelp", H(remotehelp), 0, 1, 1, CMPL0 rmthelp }, + { "rmdir", H(rmdirhelp), 0, 1, 1, CMPL(r) removedir }, + { "rstatus", H(rmtstatushelp),0, 1, 1, CMPL(r) rmtstatus }, + { "runique", H(runiquehelp), 0, 0, 1, CMPL0 setrunique }, + { "send", H(sendhelp), 1, 1, 1, CMPL(lr) put }, + { "sendport", H(porthelp), 0, 0, 0, CMPL0 setport }, + { "set", H(sethelp), 0, 0, 0, CMPL(o) setoption }, + { "site", H(sitehelp), 0, 1, 1, CMPL0 site }, + { "size", H(sizecmdhelp), 1, 1, 1, CMPL(r) sizecmd }, + { "sndbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf }, + { "status", H(statushelp), 0, 0, 1, CMPL0 status }, + { "struct", H(structhelp), 0, 1, 1, CMPL0 setstruct }, + { "sunique", H(suniquehelp), 0, 0, 1, CMPL0 setsunique }, + { "system", H(systemhelp), 0, 1, 1, CMPL0 syst }, + { "tenex", H(tenexhelp), 0, 1, 1, CMPL0 settenex }, + { "throttle", H(ratehelp), 0, 0, 0, CMPL0 setrate }, + { "trace", H(tracehelp), 0, 0, 0, CMPL0 settrace }, + { "type", H(typehelp), 0, 1, 1, CMPL0 settype }, + { "umask", H(umaskhelp), 0, 1, 1, CMPL0 do_umask }, + { "unset", H(unsethelp), 0, 0, 0, CMPL(o) unsetoption }, + { "usage", H(usagehelp), 0, 0, 1, CMPL(C) help }, + { "user", H(userhelp), 0, 1, 1, CMPL0 user }, + { "verbose", H(verbosehelp), 0, 0, 0, CMPL0 setverbose }, + { "xferbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf }, + { "?", H(helphelp), 0, 0, 1, CMPL(C) help }, + { 0 }, +}; + +struct option optiontab[] = { + { "anonpass", NULL }, + { "ftp_proxy", NULL }, + { "http_proxy", NULL }, + { "no_proxy", NULL }, + { "pager", NULL }, + { "prompt", NULL }, + { "rprompt", NULL }, + { 0 }, +}; diff --git a/contrib/tnftp/src/complete.c b/contrib/tnftp/src/complete.c new file mode 100644 index 0000000..8831bc1 --- /dev/null +++ b/contrib/tnftp/src/complete.c @@ -0,0 +1,435 @@ +/* $NetBSD: complete.c,v 1.38 2000/05/01 10:35:17 lukem Exp $ */ + +/*- + * Copyright (c) 1997-2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: complete.c,v 1.38 2000/05/01 10:35:17 lukem Exp $"); +#endif /* not lint */ + +/* + * FTP user program - command and file completion routines + */ + +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ftp_var.h" + +#ifndef NO_EDITCOMPLETE + +static int comparstr (const void *, const void *); +static unsigned char complete_ambiguous (char *, int, StringList *); +static unsigned char complete_command (char *, int); +static unsigned char complete_local (char *, int); +static unsigned char complete_option (char *, int); +static unsigned char complete_remote (char *, int); + +static int +comparstr(const void *a, const void *b) +{ + return (strcmp(*(const char **)a, *(const char **)b)); +} + +/* + * Determine if complete is ambiguous. If unique, insert. + * If no choices, error. If unambiguous prefix, insert that. + * Otherwise, list choices. words is assumed to be filtered + * to only contain possible choices. + * Args: + * word word which started the match + * list list by default + * words stringlist containing possible matches + * Returns a result as per el_set(EL_ADDFN, ...) + */ +static unsigned char +complete_ambiguous(char *word, int list, StringList *words) +{ + char insertstr[MAXPATHLEN]; + char *lastmatch, *p; + int i, j; + size_t matchlen, wordlen; + + wordlen = strlen(word); + if (words->sl_cur == 0) + return (CC_ERROR); /* no choices available */ + + if (words->sl_cur == 1) { /* only once choice available */ + p = words->sl_str[0] + wordlen; + if (*p == '\0') /* at end of word? */ + return (CC_REFRESH); + ftpvis(insertstr, sizeof(insertstr), p, strlen(p)); + if (el_insertstr(el, insertstr) == -1) + return (CC_ERROR); + else + return (CC_REFRESH); + } + + if (!list) { + matchlen = 0; + lastmatch = words->sl_str[0]; + matchlen = strlen(lastmatch); + for (i = 1 ; i < words->sl_cur ; i++) { + for (j = wordlen ; j < strlen(words->sl_str[i]); j++) + if (lastmatch[j] != words->sl_str[i][j]) + break; + if (j < matchlen) + matchlen = j; + } + if (matchlen > wordlen) { + ftpvis(insertstr, sizeof(insertstr), + lastmatch + wordlen, matchlen - wordlen); + if (el_insertstr(el, insertstr) == -1) + return (CC_ERROR); + else + return (CC_REFRESH_BEEP); + } + } + + putc('\n', ttyout); + qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr); + list_vertical(words); + return (CC_REDISPLAY); +} + +/* + * Complete a command + */ +static unsigned char +complete_command(char *word, int list) +{ + struct cmd *c; + StringList *words; + size_t wordlen; + unsigned char rv; + + words = xsl_init(); + wordlen = strlen(word); + + for (c = cmdtab; c->c_name != NULL; c++) { + if (wordlen > strlen(c->c_name)) + continue; + if (strncmp(word, c->c_name, wordlen) == 0) + xsl_add(words, c->c_name); + } + + rv = complete_ambiguous(word, list, words); + if (rv == CC_REFRESH) { + if (el_insertstr(el, " ") == -1) + rv = CC_ERROR; + } + sl_free(words, 0); + return (rv); +} + +/* + * Complete a local file + */ +static unsigned char +complete_local(char *word, int list) +{ + StringList *words; + char dir[MAXPATHLEN]; + char *file; + DIR *dd; + struct dirent *dp; + unsigned char rv; + size_t len; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '.'; + dir[1] = '\0'; + file = word; + } else { + if (file == word) { + dir[0] = '/'; + dir[1] = '\0'; + } else + (void)strlcpy(dir, word, file - word + 1); + file++; + } + if (dir[0] == '~') { + char *p; + + if ((p = globulize(dir)) == NULL) + return (CC_ERROR); + (void)strlcpy(dir, p, sizeof(dir)); + free(p); + } + + if ((dd = opendir(dir)) == NULL) + return (CC_ERROR); + + words = xsl_init(); + len = strlen(file); + + for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + +#if defined(DIRENT_MISSING_D_NAMLEN) + if (len > strlen(dp->d_name)) + continue; +#else + if (len > dp->d_namlen) + continue; +#endif + if (strncmp(file, dp->d_name, len) == 0) { + char *tcp; + + tcp = xstrdup(dp->d_name); + xsl_add(words, tcp); + } + } + closedir(dd); + + rv = complete_ambiguous(file, list, words); + if (rv == CC_REFRESH) { + struct stat sb; + char path[MAXPATHLEN]; + + (void)strlcpy(path, dir, sizeof(path)); + (void)strlcat(path, "/", sizeof(path)); + (void)strlcat(path, words->sl_str[0], sizeof(path)); + + if (stat(path, &sb) >= 0) { + char suffix[2] = " "; + + if (S_ISDIR(sb.st_mode)) + suffix[0] = '/'; + if (el_insertstr(el, suffix) == -1) + rv = CC_ERROR; + } + } + sl_free(words, 1); + return (rv); +} +/* + * Complete an option + */ +static unsigned char +complete_option(char *word, int list) +{ + struct option *o; + StringList *words; + size_t wordlen; + unsigned char rv; + + words = xsl_init(); + wordlen = strlen(word); + + for (o = optiontab; o->name != NULL; o++) { + if (wordlen > strlen(o->name)) + continue; + if (strncmp(word, o->name, wordlen) == 0) + xsl_add(words, o->name); + } + + rv = complete_ambiguous(word, list, words); + if (rv == CC_REFRESH) { + if (el_insertstr(el, " ") == -1) + rv = CC_ERROR; + } + sl_free(words, 0); + return (rv); +} + +/* + * Complete a remote file + */ +static unsigned char +complete_remote(char *word, int list) +{ + static StringList *dirlist; + static char lastdir[MAXPATHLEN]; + StringList *words; + char dir[MAXPATHLEN]; + char *file, *cp; + int i; + unsigned char rv; + + char *dummyargv[] = { "complete", NULL, NULL }; + dummyargv[1] = dir; + + if ((file = strrchr(word, '/')) == NULL) { + dir[0] = '\0'; + file = word; + } else { + cp = file; + while (*cp == '/' && cp > word) + cp--; + (void)strlcpy(dir, word, cp - word + 2); + file++; + } + + if (dirchange || dirlist == NULL || + strcmp(dir, lastdir) != 0) { /* dir not cached */ + char *emesg; + + if (dirlist != NULL) + sl_free(dirlist, 1); + dirlist = xsl_init(); + + mflag = 1; + emesg = NULL; + while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) { + char *tcp; + + if (!mflag) + continue; + if (*cp == '\0') { + mflag = 0; + continue; + } + tcp = strrchr(cp, '/'); + if (tcp) + tcp++; + else + tcp = cp; + tcp = xstrdup(tcp); + xsl_add(dirlist, tcp); + } + if (emesg != NULL) { + fprintf(ttyout, "\n%s\n", emesg); + return (CC_REDISPLAY); + } + (void)strlcpy(lastdir, dir, sizeof(lastdir)); + dirchange = 0; + } + + words = xsl_init(); + for (i = 0; i < dirlist->sl_cur; i++) { + cp = dirlist->sl_str[i]; + if (strlen(file) > strlen(cp)) + continue; + if (strncmp(file, cp, strlen(file)) == 0) + xsl_add(words, cp); + } + rv = complete_ambiguous(file, list, words); + sl_free(words, 0); + return (rv); +} + +/* + * Generic complete routine + */ +unsigned char +complete(EditLine *el, int ch) +{ + static char word[FTPBUFLEN]; + static int lastc_argc, lastc_argo; + + struct cmd *c; + const LineInfo *lf; + int celems, dolist, cmpltype; + size_t len; + + lf = el_line(el); + len = lf->lastchar - lf->buffer; + if (len >= sizeof(line)) + return (CC_ERROR); + (void)strlcpy(line, lf->buffer, len + 1); + cursor_pos = line + (lf->cursor - lf->buffer); + lastc_argc = cursor_argc; /* remember last cursor pos */ + lastc_argo = cursor_argo; + makeargv(); /* build argc/argv of current line */ + + if (cursor_argo >= sizeof(word)) + return (CC_ERROR); + + dolist = 0; + /* if cursor and word is same, list alternatives */ + if (lastc_argc == cursor_argc && lastc_argo == cursor_argo + && strncmp(word, margv[cursor_argc] ? margv[cursor_argc] : "", + cursor_argo) == 0) + dolist = 1; + else if (cursor_argc < margc) + (void)strlcpy(word, margv[cursor_argc], cursor_argo + 1); + word[cursor_argo] = '\0'; + + if (cursor_argc == 0) + return (complete_command(word, dolist)); + + c = getcmd(margv[0]); + if (c == (struct cmd *)-1 || c == 0) + return (CC_ERROR); + celems = strlen(c->c_complete); + + /* check for 'continuation' completes (which are uppercase) */ + if ((cursor_argc > celems) && (celems > 0) + && isupper((unsigned char) c->c_complete[celems-1])) + cursor_argc = celems; + + if (cursor_argc > celems) + return (CC_ERROR); + + cmpltype = c->c_complete[cursor_argc - 1]; + switch (cmpltype) { + case 'c': /* command complete */ + case 'C': + return (complete_command(word, dolist)); + case 'l': /* local complete */ + case 'L': + return (complete_local(word, dolist)); + case 'n': /* no complete */ + case 'N': /* no complete */ + return (CC_ERROR); + case 'o': /* local complete */ + case 'O': + return (complete_option(word, dolist)); + case 'r': /* remote complete */ + case 'R': + if (connected != -1) { + fputs("\nMust be logged in to complete.\n", + ttyout); + return (CC_REDISPLAY); + } + return (complete_remote(word, dolist)); + default: + errx(1, "unknown complete type `%c'", cmpltype); + return (CC_ERROR); + } + /* NOTREACHED */ +} + +#endif /* !NO_EDITCOMPLETE */ diff --git a/contrib/tnftp/src/domacro.c b/contrib/tnftp/src/domacro.c new file mode 100644 index 0000000..2e10e1c --- /dev/null +++ b/contrib/tnftp/src/domacro.c @@ -0,0 +1,143 @@ +/* $NetBSD: domacro.c,v 1.20 2003/08/07 11:13:53 agc Exp $ */ + +/* + * 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. 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 <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: domacro.c,v 1.20 2003/08/07 11:13:53 agc Exp $"); +#endif +#endif /* not lint */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> + +#include "ftp_var.h" + +void +domacro(int argc, char *argv[]) +{ + int i, j, count = 2, loopflg = 0; + char *cp1, *cp2, line2[FTPBUFLEN]; + struct cmd *c; + + if ((argc == 0 && argv != NULL) || + (argc < 2 && !another(&argc, &argv, "macro name"))) { + fprintf(ttyout, "usage: %s macro_name [args]\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) { + fprintf(ttyout, "'%s' macro not found.\n", argv[1]); + code = -1; + return; + } + (void)strlcpy(line2, line, sizeof(line2)); + TOP: + cp1 = macros[i].mac_start; + while (cp1 != macros[i].mac_end) { + while (isspace((unsigned char)*cp1)) + cp1++; + cp2 = line; + while (*cp1 != '\0') { + switch(*cp1) { + case '\\': + *cp2++ = *++cp1; + break; + case '$': + if (isdigit((unsigned char)*(cp1+1))) { + j = 0; + while (isdigit((unsigned char)*++cp1)) + j = 10*j + *cp1 - '0'; + cp1--; + if (argc - 2 >= j) { + (void)strlcpy(cp2, argv[j+1], + sizeof(line) - (cp2 - line)); + cp2 += strlen(argv[j+1]); + } + break; + } + if (*(cp1+1) == 'i') { + loopflg = 1; + cp1++; + if (count < argc) { + (void)strlcpy(cp2, argv[count], + sizeof(line) - (cp2 - line)); + 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) { + fputs("?Ambiguous command.\n", ttyout); + code = -1; + } else if (c == 0) { + fputs("?Invalid command.\n", ttyout); + code = -1; + } else if (c->c_conn && !connected) { + fputs("Not connected.\n", ttyout); + code = -1; + } else { + if (verbose) { + fputs(line, ttyout); + putc('\n', ttyout); + } + margv[0] = c->c_name; + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) + (void)putc('\007', ttyout); + (void)strlcpy(line, line2, sizeof(line)); + makeargv(); + argc = margc; + argv = margv; + } + if (cp1 != macros[i].mac_end) + cp1++; + } + if (loopflg && ++count < argc) + goto TOP; +} diff --git a/contrib/tnftp/src/extern.h b/contrib/tnftp/src/extern.h new file mode 100644 index 0000000..f2b802a --- /dev/null +++ b/contrib/tnftp/src/extern.h @@ -0,0 +1,257 @@ +/* $NetBSD: extern.h,v 1.67 2005/05/14 15:26:43 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 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. 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 + */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +struct sockaddr; +struct tm; +struct addrinfo; + +void abort_remote(FILE *); +void abort_squared(int); +void abortpt(int); +void abortxfer(int); +void account(int, char **); +void ai_unmapped(struct addrinfo *); +int another(int *, char ***, const char *); +int auto_fetch(int, char **); +int auto_put(int, char **, const char *); +void blkfree(char **); +void cd(int, char **); +void cdup(int, char **); +void changetype(int, int); +void cleanuppeer(void); +void cmdabort(int); +void cmdtimeout(int); +void cmdscanner(void); +int command(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +#ifndef NO_EDITCOMPLETE +unsigned char complete(EditLine *, int); +void controlediting(void); +#endif /* !NO_EDITCOMPLETE */ +void crankrate(int); +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 **); +void doproxy(int, char **); +void feat(int, char **); +void fget(int, char **); +int fileindir(const char *, const char *); +int foregroundproc(void); +void formatbuf(char *, size_t, const char *); +void ftpvis(char *, size_t, const char *, size_t); +int ftp_login(const char *, const char *, const char *); +void get(int, char **); +struct cmd *getcmd(const char *); +int getit(int, char **, int, const char *); +struct option *getoption(const char *); +char *getoptionvalue(const char *); +void getremoteinfo(void); +int getreply(int); +char *globulize(const char *); +char *gunique(const char *); +void help(int, char **); +char *hookup(char *, char *); +void idlecmd(int, char **); +int initconn(void); +void intr(int); +int isipv6addr(const char *); +void list_vertical(StringList *); +void lcd(int, char **); +void lostpeer(int); +void lpage(int, char **); +void lpwd(int, char **); +void ls(int, char **); +void mabort(void); +void macdef(int, char **); +void makeargv(void); +void makedir(int, char **); +void mdelete(int, char **); +void mget(int, char **); +void mintr(int); +void mls(int, char **); +void mlst(int, char **); +void modtime(int, char **); +void mput(int, char **); +char *onoff(int); +void opts(int, char **); +void newer(int, char **); +void page(int, char **); +int parseport(const char *, int); +int parserate(int, char **, int); +char *prompt(void); +void proxabort(int); +void proxtrans(const char *, const char *, const char *); +void psabort(int); +void pswitch(int); +void put(int, char **); +void pwd(int, char **); +void quit(int, char **); +void quote(int, char **); +void quote1(const char *, int, char **); +void recvrequest(const char *, const char *, const char *, + const char *, int, int); +void reget(int, char **); +char *remglob(char **, int, char **); +time_t remotemodtime(const char *, int); +off_t remotesize(const 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 **); +char *rprompt(void); +int ruserpass(const char *, const char **, const char **, + const char **); +void sendrequest(const char *, const char *, const 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 setedit(int, char **); +void setepsv4(int, char **); +void setform(int, char **); +void setftmode(int, char **); +void setgate(int, char **); +void setglob(int, char **); +void sethash(int, char **); +void setnmap(int, char **); +void setntrans(int, char **); +void setoption(int, char **); +void setpassive(int, char **); +void setpeer(int, char **); +void setport(int, char **); +void setpreserve(int, char **); +void setprogress(int, char **); +void setprompt(int, char **); +void setrate(int, char **); +void setrunique(int, char **); +void setstruct(int, char **); +void setsunique(int, char **); +void settenex(int, char **); +void settrace(int, char **); +void setttywidth(int); +void settype(int, char **); +void setupsockbufsize(int); +void setverbose(int, char **); +void setxferbuf(int, char **); +void shell(int, char **); +void site(int, char **); +void sizecmd(int, char **); +char *slurpstring(void); +void status(int, char **); +int strsuftoi(const char *); +void syst(int, char **); +int togglevar(int, char **, int *, const char *); +void unsetoption(int, char **); +void updatelocalcwd(void); +void updateremotecwd(void); +void usage(void); +void user(int, char **); +int xconnect(int, const struct sockaddr *, socklen_t); +int xlisten(int, int); +int xpoll(struct pollfd *, int, int); +void *xmalloc(size_t); +StringList *xsl_init(void); +void xsl_add(StringList *, char *); +char *xstrdup(const char *); diff --git a/contrib/tnftp/src/fetch.c b/contrib/tnftp/src/fetch.c new file mode 100644 index 0000000..e2acb01 --- /dev/null +++ b/contrib/tnftp/src/fetch.c @@ -0,0 +1,1834 @@ +/* $NetBSD: fetch.c,v 1.158 2005/05/14 15:26:43 lukem Exp $ */ + +/*- + * Copyright (c) 1997-2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Scott Aaron Bamford. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: fetch.c,v 1.158 2005/05/14 15:26:43 lukem Exp $"); +#endif /* not lint */ + +/* + * FTP User Program -- Command line file retrieval + */ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/time.h> + +#include <netinet/in.h> + +#include <arpa/ftp.h> +#include <arpa/inet.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <time.h> +#include <libutil.h> + +#include "ftp_var.h" +#include "version.h" + +typedef enum { + UNKNOWN_URL_T=-1, + HTTP_URL_T, + FTP_URL_T, + FILE_URL_T, + CLASSIC_URL_T +} url_t; + +void aborthttp(int); +#ifndef NO_AUTH +static int auth_url(const char *, char **, const char *, const char *); +static void base64_encode(const unsigned char *, size_t, unsigned char *); +#endif +static int go_fetch(const char *); +static int fetch_ftp(const char *); +static int fetch_url(const char *, const char *, char *, char *); +static const char *match_token(const char **, const char *); +static int parse_url(const char *, const char *, url_t *, char **, + char **, char **, char **, in_port_t *, char **); +static void url_decode(char *); + +static int redirect_loop; + + +#define STRNEQUAL(a,b) (strncasecmp((a), (b), sizeof((b))-1) == 0) +#define ISLWS(x) ((x)=='\r' || (x)=='\n' || (x)==' ' || (x)=='\t') +#define SKIPLWS(x) do { while (ISLWS((*x))) x++; } while (0) + + +#define ABOUT_URL "about:" /* propaganda */ +#define FILE_URL "file://" /* file URL prefix */ +#define FTP_URL "ftp://" /* ftp URL prefix */ +#define HTTP_URL "http://" /* http URL prefix */ + + +/* + * Determine if token is the next word in buf (case insensitive). + * If so, advance buf past the token and any trailing LWS, and + * return a pointer to the token (in buf). Otherwise, return NULL. + * token may be preceeded by LWS. + * token must be followed by LWS or NUL. (I.e, don't partial match). + */ +static const char * +match_token(const char **buf, const char *token) +{ + const char *p, *orig; + size_t tlen; + + tlen = strlen(token); + p = *buf; + SKIPLWS(p); + orig = p; + if (strncasecmp(p, token, tlen) != 0) + return NULL; + p += tlen; + if (*p != '\0' && !ISLWS(*p)) + return NULL; + SKIPLWS(p); + orig = *buf; + *buf = p; + return orig; +} + +#ifndef NO_AUTH +/* + * Generate authorization response based on given authentication challenge. + * Returns -1 if an error occurred, otherwise 0. + * Sets response to a malloc(3)ed string; caller should free. + */ +static int +auth_url(const char *challenge, char **response, const char *guser, + const char *gpass) +{ + const char *cp, *scheme; + char *ep, *clear, *realm; + char user[BUFSIZ], *pass; + int rval; + size_t len, clen, rlen; + + *response = NULL; + clear = realm = NULL; + rval = -1; + cp = challenge; + scheme = "Basic"; /* only support Basic authentication */ + + if (debug) + fprintf(ttyout, "auth_url: challenge `%s'\n", challenge); + + if (! match_token(&cp, scheme)) { + warnx("Unsupported authentication challenge - `%s'", + challenge); + goto cleanup_auth_url; + } + +#define REALM "realm=\"" + if (STRNEQUAL(cp, REALM)) + cp += sizeof(REALM) - 1; + else { + warnx("Unsupported authentication challenge - `%s'", + challenge); + goto cleanup_auth_url; + } +/* XXX: need to improve quoted-string parsing to support \ quoting, etc. */ + if ((ep = strchr(cp, '\"')) != NULL) { + size_t len = ep - cp; + + realm = (char *)xmalloc(len + 1); + (void)strlcpy(realm, cp, len + 1); + } else { + warnx("Unsupported authentication challenge - `%s'", + challenge); + goto cleanup_auth_url; + } + + fprintf(ttyout, "Username for `%s': ", realm); + if (guser != NULL) { + (void)strlcpy(user, guser, sizeof(user)); + fprintf(ttyout, "%s\n", user); + } else { + (void)fflush(ttyout); + if (fgets(user, sizeof(user) - 1, stdin) == NULL) { + clearerr(stdin); + goto cleanup_auth_url; + } + user[strlen(user) - 1] = '\0'; + } + if (gpass != NULL) + pass = (char *)gpass; + else + pass = getpass("Password: "); + + clen = strlen(user) + strlen(pass) + 2; /* user + ":" + pass + "\0" */ + clear = (char *)xmalloc(clen); + (void)strlcpy(clear, user, clen); + (void)strlcat(clear, ":", clen); + (void)strlcat(clear, pass, clen); + if (gpass == NULL) + memset(pass, 0, strlen(pass)); + + /* scheme + " " + enc + "\0" */ + rlen = strlen(scheme) + 1 + (clen + 2) * 4 / 3 + 1; + *response = (char *)xmalloc(rlen); + (void)strlcpy(*response, scheme, rlen); + len = strlcat(*response, " ", rlen); + /* use `clen - 1' to not encode the trailing NUL */ + base64_encode((unsigned char *)clear, clen - 1, + (unsigned char *)*response + len); + memset(clear, 0, clen); + rval = 0; + + cleanup_auth_url: + FREEPTR(clear); + FREEPTR(realm); + return (rval); +} + +/* + * Encode len bytes starting at clear using base64 encoding into encoded, + * which should be at least ((len + 2) * 4 / 3 + 1) in size. + */ +static void +base64_encode(const unsigned char *clear, size_t len, unsigned char *encoded) +{ + static const unsigned char enc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + unsigned char *cp; + int i; + + cp = encoded; + for (i = 0; i < len; i += 3) { + *(cp++) = enc[((clear[i + 0] >> 2))]; + *(cp++) = enc[((clear[i + 0] << 4) & 0x30) + | ((clear[i + 1] >> 4) & 0x0f)]; + *(cp++) = enc[((clear[i + 1] << 2) & 0x3c) + | ((clear[i + 2] >> 6) & 0x03)]; + *(cp++) = enc[((clear[i + 2] ) & 0x3f)]; + } + *cp = '\0'; + while (i-- > len) + *(--cp) = '='; +} +#endif + +/* + * Decode %xx escapes in given string, `in-place'. + */ +static void +url_decode(char *url) +{ + unsigned char *p, *q; + + if (EMPTYSTRING(url)) + return; + p = q = (unsigned char *)url; + +#define HEXTOINT(x) (x - (isdigit(x) ? '0' : (islower(x) ? 'a' : 'A') - 10)) + while (*p) { + if (p[0] == '%' + && p[1] && isxdigit((unsigned char)p[1]) + && p[2] && isxdigit((unsigned char)p[2])) { + *q++ = HEXTOINT(p[1]) * 16 + HEXTOINT(p[2]); + p+=3; + } else + *q++ = *p++; + } + *q = '\0'; +} + + +/* + * Parse URL of form: + * <type>://[<user>[:<password>]@]<host>[:<port>][/<path>] + * Returns -1 if a parse error occurred, otherwise 0. + * It's the caller's responsibility to url_decode() the returned + * user, pass and path. + * + * Sets type to url_t, each of the given char ** pointers to a + * malloc(3)ed strings of the relevant section, and port to + * the number given, or ftpport if ftp://, or httpport if http://. + * + * If <host> is surrounded by `[' and ']', it's parsed as an + * IPv6 address (as per RFC 2732). + * + * XXX: this is not totally RFC 1738 compliant; <path> will have the + * leading `/' unless it's an ftp:// URL, as this makes things easier + * for file:// and http:// URLs. ftp:// URLs have the `/' between the + * host and the URL-path removed, but any additional leading slashes + * in the URL-path are retained (because they imply that we should + * later do "CWD" with a null argument). + * + * Examples: + * input URL output path + * --------- ----------- + * "ftp://host" NULL + * "http://host/" NULL + * "file://host/dir/file" "dir/file" + * "ftp://host/" "" + * "ftp://host//" NULL + * "ftp://host//dir/file" "/dir/file" + */ +static int +parse_url(const char *url, const char *desc, url_t *type, + char **user, char **pass, char **host, char **port, + in_port_t *portnum, char **path) +{ + const char *origurl; + char *cp, *ep, *thost, *tport; + size_t len; + + if (url == NULL || desc == NULL || type == NULL || user == NULL + || pass == NULL || host == NULL || port == NULL || portnum == NULL + || path == NULL) + errx(1, "parse_url: invoked with NULL argument!"); + + origurl = url; + *type = UNKNOWN_URL_T; + *user = *pass = *host = *port = *path = NULL; + *portnum = 0; + tport = NULL; + + if (STRNEQUAL(url, HTTP_URL)) { + url += sizeof(HTTP_URL) - 1; + *type = HTTP_URL_T; + *portnum = HTTP_PORT; + tport = httpport; + } else if (STRNEQUAL(url, FTP_URL)) { + url += sizeof(FTP_URL) - 1; + *type = FTP_URL_T; + *portnum = FTP_PORT; + tport = ftpport; + } else if (STRNEQUAL(url, FILE_URL)) { + url += sizeof(FILE_URL) - 1; + *type = FILE_URL_T; + } else { + warnx("Invalid %s `%s'", desc, url); + cleanup_parse_url: + FREEPTR(*user); + FREEPTR(*pass); + FREEPTR(*host); + FREEPTR(*port); + FREEPTR(*path); + return (-1); + } + + if (*url == '\0') + return (0); + + /* find [user[:pass]@]host[:port] */ + ep = strchr(url, '/'); + if (ep == NULL) + thost = xstrdup(url); + else { + len = ep - url; + thost = (char *)xmalloc(len + 1); + (void)strlcpy(thost, url, len + 1); + if (*type == FTP_URL_T) /* skip first / for ftp URLs */ + ep++; + *path = xstrdup(ep); + } + + cp = strchr(thost, '@'); /* look for user[:pass]@ in URLs */ + if (cp != NULL) { + if (*type == FTP_URL_T) + anonftp = 0; /* disable anonftp */ + *user = thost; + *cp = '\0'; + thost = xstrdup(cp + 1); + cp = strchr(*user, ':'); + if (cp != NULL) { + *cp = '\0'; + *pass = xstrdup(cp + 1); + } + url_decode(*user); + if (*pass) + url_decode(*pass); + } + +#ifdef INET6 + /* + * Check if thost is an encoded IPv6 address, as per + * RFC 2732: + * `[' ipv6-address ']' + */ + if (*thost == '[') { + cp = thost + 1; + if ((ep = strchr(cp, ']')) == NULL || + (ep[1] != '\0' && ep[1] != ':')) { + warnx("Invalid address `%s' in %s `%s'", + thost, desc, origurl); + goto cleanup_parse_url; + } + len = ep - cp; /* change `[xyz]' -> `xyz' */ + memmove(thost, thost + 1, len); + thost[len] = '\0'; + if (! isipv6addr(thost)) { + warnx("Invalid IPv6 address `%s' in %s `%s'", + thost, desc, origurl); + goto cleanup_parse_url; + } + cp = ep + 1; + if (*cp == ':') + cp++; + else + cp = NULL; + } else +#endif /* INET6 */ + if ((cp = strchr(thost, ':')) != NULL) + *cp++ = '\0'; + *host = thost; + + /* look for [:port] */ + if (cp != NULL) { + long nport; + + nport = parseport(cp, -1); + if (nport == -1) { + warnx("Unknown port `%s' in %s `%s'", + cp, desc, origurl); + goto cleanup_parse_url; + } + *portnum = nport; + tport = cp; + } + + if (tport != NULL) + *port = xstrdup(tport); + if (*path == NULL) + *path = xstrdup("/"); + + if (debug) + fprintf(ttyout, + "parse_url: user `%s' pass `%s' host %s port %s(%d) " + "path `%s'\n", + *user ? *user : "<null>", *pass ? *pass : "<null>", + *host ? *host : "<null>", *port ? *port : "<null>", + *portnum ? *portnum : -1, *path ? *path : "<null>"); + + return (0); +} + +sigjmp_buf httpabort; + +/* + * Retrieve URL, via a proxy if necessary, using HTTP. + * If proxyenv is set, use that for the proxy, otherwise try ftp_proxy or + * http_proxy as appropriate. + * Supports HTTP redirects. + * Returns 1 on failure, 0 on completed xfer, -1 if ftp connection + * is still open (e.g, ftp xfer with trailing /) + */ +static int +fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth) +{ + struct addrinfo hints, *res, *res0 = NULL; + int error; + char hbuf[NI_MAXHOST]; + volatile sigfunc oldintr, oldintp; + volatile int s; + struct stat sb; + int ischunked, isproxy, rval, hcode; + size_t len; + static size_t bufsize; + static char *xferbuf; + const char *cp, *token; + char *ep, *buf, *savefile; + char *auth, *location, *message; + char *user, *pass, *host, *port, *path, *decodedpath; + char *puser, *ppass, *useragent; + off_t hashbytes, rangestart, rangeend, entitylen; + int (*closefunc)(FILE *); + FILE *fin, *fout; + time_t mtime; + url_t urltype; + in_port_t portnum; + + oldintr = oldintp = NULL; + closefunc = NULL; + fin = fout = NULL; + s = -1; + buf = savefile = NULL; + auth = location = message = NULL; + ischunked = isproxy = hcode = 0; + rval = 1; + user = pass = host = path = decodedpath = puser = ppass = NULL; + +#ifdef __GNUC__ /* shut up gcc warnings */ + (void)&closefunc; + (void)&fin; + (void)&fout; + (void)&buf; + (void)&savefile; + (void)&rval; + (void)&isproxy; + (void)&hcode; + (void)&ischunked; + (void)&message; + (void)&location; + (void)&auth; + (void)&decodedpath; +#endif + + if (parse_url(url, "URL", &urltype, &user, &pass, &host, &port, + &portnum, &path) == -1) + goto cleanup_fetch_url; + + if (urltype == FILE_URL_T && ! EMPTYSTRING(host) + && strcasecmp(host, "localhost") != 0) { + warnx("No support for non local file URL `%s'", url); + goto cleanup_fetch_url; + } + + if (EMPTYSTRING(path)) { + if (urltype == FTP_URL_T) { + rval = fetch_ftp(url); + goto cleanup_fetch_url; + } + if (urltype != HTTP_URL_T || outfile == NULL) { + warnx("Invalid URL (no file after host) `%s'", url); + goto cleanup_fetch_url; + } + } + + decodedpath = xstrdup(path); + url_decode(decodedpath); + + if (outfile) + savefile = xstrdup(outfile); + else { + cp = strrchr(decodedpath, '/'); /* find savefile */ + if (cp != NULL) + savefile = xstrdup(cp + 1); + else + savefile = xstrdup(decodedpath); + } + if (EMPTYSTRING(savefile)) { + if (urltype == FTP_URL_T) { + rval = fetch_ftp(url); + goto cleanup_fetch_url; + } + warnx("no file after directory (you must specify an " + "output file) `%s'", url); + goto cleanup_fetch_url; + } else { + if (debug) + fprintf(ttyout, "savefile `%s'\n", savefile); + } + + restart_point = 0; + filesize = -1; + rangestart = rangeend = entitylen = -1; + mtime = -1; + if (restartautofetch) { + if (strcmp(savefile, "-") != 0 && *savefile != '|' && + stat(savefile, &sb) == 0) + restart_point = sb.st_size; + } + if (urltype == FILE_URL_T) { /* file:// URLs */ + direction = "copied"; + fin = fopen(decodedpath, "r"); + if (fin == NULL) { + warn("Cannot open file `%s'", decodedpath); + goto cleanup_fetch_url; + } + if (fstat(fileno(fin), &sb) == 0) { + mtime = sb.st_mtime; + filesize = sb.st_size; + } + if (restart_point) { + if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) { + warn("Can't lseek to restart `%s'", + decodedpath); + goto cleanup_fetch_url; + } + } + if (verbose) { + fprintf(ttyout, "Copying %s", decodedpath); + if (restart_point) + fprintf(ttyout, " (restarting at " LLF ")", + (LLT)restart_point); + fputs("\n", ttyout); + } + } else { /* ftp:// or http:// URLs */ + char *leading; + int hasleading; + + if (proxyenv == NULL) { + if (urltype == HTTP_URL_T) + proxyenv = getoptionvalue("http_proxy"); + else if (urltype == FTP_URL_T) + proxyenv = getoptionvalue("ftp_proxy"); + } + direction = "retrieved"; + if (! EMPTYSTRING(proxyenv)) { /* use proxy */ + url_t purltype; + char *phost, *ppath; + char *pport, *no_proxy; + + isproxy = 1; + + /* check URL against list of no_proxied sites */ + no_proxy = getoptionvalue("no_proxy"); + if (! EMPTYSTRING(no_proxy)) { + char *np, *np_copy; + long np_port; + size_t hlen, plen; + + np_copy = xstrdup(no_proxy); + hlen = strlen(host); + while ((cp = strsep(&np_copy, " ,")) != NULL) { + if (*cp == '\0') + continue; + if ((np = strrchr(cp, ':')) != NULL) { + *np = '\0'; + np_port = + strtol(np + 1, &ep, 10); + if (*ep != '\0') + continue; + if (np_port != portnum) + continue; + } + plen = strlen(cp); + if (hlen < plen) + continue; + if (strncasecmp(host + hlen - plen, + cp, plen) == 0) { + isproxy = 0; + break; + } + } + FREEPTR(np_copy); + if (isproxy == 0 && urltype == FTP_URL_T) { + rval = fetch_ftp(url); + goto cleanup_fetch_url; + } + } + + if (isproxy) { + if (parse_url(proxyenv, "proxy URL", &purltype, + &puser, &ppass, &phost, &pport, &portnum, + &ppath) == -1) + goto cleanup_fetch_url; + + if ((purltype != HTTP_URL_T + && purltype != FTP_URL_T) || + EMPTYSTRING(phost) || + (! EMPTYSTRING(ppath) + && strcmp(ppath, "/") != 0)) { + warnx("Malformed proxy URL `%s'", + proxyenv); + FREEPTR(phost); + FREEPTR(pport); + FREEPTR(ppath); + goto cleanup_fetch_url; + } + if (isipv6addr(host) && + strchr(host, '%') != NULL) { + warnx( +"Scoped address notation `%s' disallowed via web proxy", + host); + FREEPTR(phost); + FREEPTR(pport); + FREEPTR(ppath); + goto cleanup_fetch_url; + } + + FREEPTR(host); + host = phost; + FREEPTR(port); + port = pport; + FREEPTR(path); + path = xstrdup(url); + FREEPTR(ppath); + } + } /* ! EMPTYSTRING(proxyenv) */ + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = 0; + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(host, NULL, &hints, &res0); + if (error) { + warnx("%s", gai_strerror(error)); + goto cleanup_fetch_url; + } + if (res0->ai_canonname) + host = res0->ai_canonname; + + s = -1; + for (res = res0; res; res = res->ai_next) { + /* + * see comment in hookup() + */ + ai_unmapped(res); + if (getnameinfo(res->ai_addr, res->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0) + strlcpy(hbuf, "invalid", sizeof(hbuf)); + + if (verbose && res != res0) + fprintf(ttyout, "Trying %s...\n", hbuf); + + ((struct sockaddr_in *)res->ai_addr)->sin_port = + htons(portnum); + s = socket(res->ai_family, SOCK_STREAM, + res->ai_protocol); + if (s < 0) { + warn("Can't create socket"); + continue; + } + + if (xconnect(s, res->ai_addr, res->ai_addrlen) < 0) { + warn("Connect to address `%s'", hbuf); + close(s); + s = -1; + continue; + } + + /* success */ + break; + } + + if (s < 0) { + warn("Can't connect to %s", host); + goto cleanup_fetch_url; + } + + fin = fdopen(s, "r+"); + /* + * Construct and send the request. + */ + if (verbose) + fprintf(ttyout, "Requesting %s\n", url); + leading = " ("; + hasleading = 0; + if (isproxy) { + if (verbose) { + fprintf(ttyout, "%svia %s:%s", leading, + host, port); + leading = ", "; + hasleading++; + } + fprintf(fin, "GET %s HTTP/1.0\r\n", path); + if (flushcache) + fprintf(fin, "Pragma: no-cache\r\n"); + } else { + fprintf(fin, "GET %s HTTP/1.1\r\n", path); + if (strchr(host, ':')) { + char *h, *p; + + /* + * strip off IPv6 scope identifier, since it is + * local to the node + */ + h = xstrdup(host); + if (isipv6addr(h) && + (p = strchr(h, '%')) != NULL) { + *p = '\0'; + } + fprintf(fin, "Host: [%s]", h); + free(h); + } else + fprintf(fin, "Host: %s", host); + if (portnum != HTTP_PORT) + fprintf(fin, ":%u", portnum); + fprintf(fin, "\r\n"); + fprintf(fin, "Accept: */*\r\n"); + fprintf(fin, "Connection: close\r\n"); + if (restart_point) { + fputs(leading, ttyout); + fprintf(fin, "Range: bytes=" LLF "-\r\n", + (LLT)restart_point); + fprintf(ttyout, "restarting at " LLF, + (LLT)restart_point); + leading = ", "; + hasleading++; + } + if (flushcache) + fprintf(fin, "Cache-Control: no-cache\r\n"); + } + if ((useragent=getenv("FTPUSERAGENT")) != NULL) { + fprintf(fin, "User-Agent: %s\r\n", useragent); + } else { + fprintf(fin, "User-Agent: %s/%s\r\n", + FTP_PRODUCT, FTP_VERSION); + } + if (wwwauth) { + if (verbose) { + fprintf(ttyout, "%swith authorization", + leading); + leading = ", "; + hasleading++; + } + fprintf(fin, "Authorization: %s\r\n", wwwauth); + } + if (proxyauth) { + if (verbose) { + fprintf(ttyout, + "%swith proxy authorization", leading); + leading = ", "; + hasleading++; + } + fprintf(fin, "Proxy-Authorization: %s\r\n", proxyauth); + } + if (verbose && hasleading) + fputs(")\n", ttyout); + fprintf(fin, "\r\n"); + if (fflush(fin) == EOF) { + warn("Writing HTTP request"); + goto cleanup_fetch_url; + } + + /* Read the response */ + if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0)) == NULL) { + warn("Receiving HTTP reply"); + goto cleanup_fetch_url; + } + while (len > 0 && (ISLWS(buf[len-1]))) + buf[--len] = '\0'; + if (debug) + fprintf(ttyout, "received `%s'\n", buf); + + /* Determine HTTP response code */ + cp = strchr(buf, ' '); + if (cp == NULL) + goto improper; + else + cp++; + hcode = strtol(cp, &ep, 10); + if (*ep != '\0' && !isspace((unsigned char)*ep)) + goto improper; + message = xstrdup(cp); + + /* Read the rest of the header. */ + while (1) { + FREEPTR(buf); + if ((buf = fparseln(fin, &len, NULL, "\0\0\0", 0)) + == NULL) { + warn("Receiving HTTP reply"); + goto cleanup_fetch_url; + } + while (len > 0 && (ISLWS(buf[len-1]))) + buf[--len] = '\0'; + if (len == 0) + break; + if (debug) + fprintf(ttyout, "received `%s'\n", buf); + + /* + * Look for some headers + */ + + cp = buf; + + if (match_token(&cp, "Content-Length:")) { + filesize = STRTOLL(cp, &ep, 10); + if (filesize < 0 || *ep != '\0') + goto improper; + if (debug) + fprintf(ttyout, + "parsed len as: " LLF "\n", + (LLT)filesize); + + } else if (match_token(&cp, "Content-Range:")) { + if (! match_token(&cp, "bytes")) + goto improper; + + if (*cp == '*') + cp++; + else { + rangestart = STRTOLL(cp, &ep, 10); + if (rangestart < 0 || *ep != '-') + goto improper; + cp = ep + 1; + rangeend = STRTOLL(cp, &ep, 10); + if (rangeend < 0 || rangeend < rangestart) + goto improper; + cp = ep; + } + if (*cp != '/') + goto improper; + cp++; + if (*cp == '*') + cp++; + else { + entitylen = STRTOLL(cp, &ep, 10); + if (entitylen < 0) + goto improper; + cp = ep; + } + if (*cp != '\0') + goto improper; + + if (debug) { + fprintf(ttyout, "parsed range as: "); + if (rangestart == -1) + fprintf(ttyout, "*"); + else + fprintf(ttyout, LLF "-" LLF, + (LLT)rangestart, + (LLT)rangeend); + fprintf(ttyout, "/" LLF "\n", (LLT)entitylen); + } + if (! restart_point) { + warnx( + "Received unexpected Content-Range header"); + goto cleanup_fetch_url; + } + + } else if (match_token(&cp, "Last-Modified:")) { + struct tm parsed; + char *t; + + /* RFC 1123 */ + if ((t = strptime(cp, + "%a, %d %b %Y %H:%M:%S GMT", + &parsed)) + /* RFC 850 */ + || (t = strptime(cp, + "%a, %d-%b-%y %H:%M:%S GMT", + &parsed)) + /* asctime */ + || (t = strptime(cp, + "%a, %b %d %H:%M:%S %Y", + &parsed))) { + parsed.tm_isdst = -1; + if (*t == '\0') + mtime = timegm(&parsed); + if (debug && mtime != -1) { + fprintf(ttyout, + "parsed date as: %s", + ctime(&mtime)); + } + } + + } else if (match_token(&cp, "Location:")) { + location = xstrdup(cp); + if (debug) + fprintf(ttyout, + "parsed location as `%s'\n", cp); + + } else if (match_token(&cp, "Transfer-Encoding:")) { + if (match_token(&cp, "binary")) { + warnx( + "Bogus transfer encoding - `binary' (fetching anyway)"); + continue; + } + if (! (token = match_token(&cp, "chunked"))) { + warnx( + "Unsupported transfer encoding - `%s'", + token); + goto cleanup_fetch_url; + } + ischunked++; + if (debug) + fprintf(ttyout, + "using chunked encoding\n"); + + } else if (match_token(&cp, "Proxy-Authenticate:") + || match_token(&cp, "WWW-Authenticate:")) { + if (! (token = match_token(&cp, "Basic"))) { + if (debug) + fprintf(ttyout, + "skipping unknown auth scheme `%s'\n", + token); + continue; + } + FREEPTR(auth); + auth = xstrdup(token); + if (debug) + fprintf(ttyout, + "parsed auth as `%s'\n", cp); + } + + } + /* finished parsing header */ + FREEPTR(buf); + + switch (hcode) { + case 200: + break; + case 206: + if (! restart_point) { + warnx("Not expecting partial content header"); + goto cleanup_fetch_url; + } + break; + case 300: + case 301: + case 302: + case 303: + case 305: + if (EMPTYSTRING(location)) { + warnx( + "No redirection Location provided by server"); + goto cleanup_fetch_url; + } + if (redirect_loop++ > 5) { + warnx("Too many redirections requested"); + goto cleanup_fetch_url; + } + if (hcode == 305) { + if (verbose) + fprintf(ttyout, "Redirected via %s\n", + location); + rval = fetch_url(url, location, + proxyauth, wwwauth); + } else { + if (verbose) + fprintf(ttyout, "Redirected to %s\n", + location); + rval = go_fetch(location); + } + goto cleanup_fetch_url; +#ifndef NO_AUTH + case 401: + case 407: + { + char **authp; + char *auser, *apass; + + if (hcode == 401) { + authp = &wwwauth; + auser = user; + apass = pass; + } else { + authp = &proxyauth; + auser = puser; + apass = ppass; + } + if (verbose || *authp == NULL || + auser == NULL || apass == NULL) + fprintf(ttyout, "%s\n", message); + if (EMPTYSTRING(auth)) { + warnx( + "No authentication challenge provided by server"); + goto cleanup_fetch_url; + } + if (*authp != NULL) { + char reply[10]; + + fprintf(ttyout, + "Authorization failed. Retry (y/n)? "); + if (fgets(reply, sizeof(reply), stdin) + == NULL) { + clearerr(stdin); + goto cleanup_fetch_url; + } + if (tolower((unsigned char)reply[0]) != 'y') + goto cleanup_fetch_url; + auser = NULL; + apass = NULL; + } + if (auth_url(auth, authp, auser, apass) == 0) { + rval = fetch_url(url, proxyenv, + proxyauth, wwwauth); + memset(*authp, 0, strlen(*authp)); + FREEPTR(*authp); + } + goto cleanup_fetch_url; + } +#endif + default: + if (message) + warnx("Error retrieving file - `%s'", message); + else + warnx("Unknown error retrieving file"); + goto cleanup_fetch_url; + } + } /* end of ftp:// or http:// specific setup */ + + /* Open the output file. */ + if (strcmp(savefile, "-") == 0) { + fout = stdout; + } else if (*savefile == '|') { + oldintp = xsignal(SIGPIPE, SIG_IGN); + fout = popen(savefile + 1, "w"); + if (fout == NULL) { + warn("Can't run `%s'", savefile + 1); + goto cleanup_fetch_url; + } + closefunc = pclose; + } else { + if ((rangeend != -1 && rangeend <= restart_point) || + (rangestart == -1 && filesize != -1 && filesize <= restart_point)) { + /* already done */ + if (verbose) + fprintf(ttyout, "already done\n"); + rval = 0; + goto cleanup_fetch_url; + } + if (restart_point && rangestart != -1) { + if (entitylen != -1) + filesize = entitylen; + if (rangestart != restart_point) { + warnx( + "Size of `%s' differs from save file `%s'", + url, savefile); + goto cleanup_fetch_url; + } + fout = fopen(savefile, "a"); + } else + fout = fopen(savefile, "w"); + if (fout == NULL) { + warn("Can't open `%s'", savefile); + goto cleanup_fetch_url; + } + closefunc = fclose; + } + + /* Trap signals */ + if (sigsetjmp(httpabort, 1)) + goto cleanup_fetch_url; + (void)xsignal(SIGQUIT, psummary); + oldintr = xsignal(SIGINT, aborthttp); + + if (rcvbuf_size > bufsize) { + if (xferbuf) + (void)free(xferbuf); + bufsize = rcvbuf_size; + xferbuf = xmalloc(bufsize); + } + + bytes = 0; + hashbytes = mark; + progressmeter(-1); + + /* Finally, suck down the file. */ + do { + long chunksize; + + chunksize = 0; + /* read chunksize */ + if (ischunked) { + if (fgets(xferbuf, bufsize, fin) == NULL) { + warnx("Unexpected EOF reading chunksize"); + goto cleanup_fetch_url; + } + chunksize = strtol(xferbuf, &ep, 16); + + /* + * XXX: Work around bug in Apache 1.3.9 and + * 1.3.11, which incorrectly put trailing + * space after the chunksize. + */ + while (*ep == ' ') + ep++; + + if (strcmp(ep, "\r\n") != 0) { + warnx("Unexpected data following chunksize"); + goto cleanup_fetch_url; + } + if (debug) + fprintf(ttyout, "got chunksize of " LLF "\n", + (LLT)chunksize); + if (chunksize == 0) + break; + } + /* transfer file or chunk */ + while (1) { + struct timeval then, now, td; + off_t bufrem; + + if (rate_get) + (void)gettimeofday(&then, NULL); + bufrem = rate_get ? rate_get : bufsize; + if (ischunked) + bufrem = MIN(chunksize, bufrem); + while (bufrem > 0) { + len = fread(xferbuf, sizeof(char), + MIN(bufsize, bufrem), fin); + if (len <= 0) + goto chunkdone; + bytes += len; + bufrem -= len; + if (fwrite(xferbuf, sizeof(char), len, fout) + != len) { + warn("Writing `%s'", savefile); + goto cleanup_fetch_url; + } + if (hash && !progress) { + while (bytes >= hashbytes) { + (void)putc('#', ttyout); + hashbytes += mark; + } + (void)fflush(ttyout); + } + if (ischunked) { + chunksize -= len; + if (chunksize <= 0) + break; + } + } + if (rate_get) { + while (1) { + (void)gettimeofday(&now, NULL); + timersub(&now, &then, &td); + if (td.tv_sec > 0) + break; + usleep(1000000 - td.tv_usec); + } + } + if (ischunked && chunksize <= 0) + break; + } + /* read CRLF after chunk*/ + chunkdone: + if (ischunked) { + if (fgets(xferbuf, bufsize, fin) == NULL) + break; + if (strcmp(xferbuf, "\r\n") != 0) { + warnx("Unexpected data following chunk"); + goto cleanup_fetch_url; + } + } + } while (ischunked); + if (hash && !progress && bytes > 0) { + if (bytes < mark) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + } + if (ferror(fin)) { + warn("Reading file"); + goto cleanup_fetch_url; + } + progressmeter(1); + (void)fflush(fout); + if (closefunc == fclose && mtime != -1) { + struct timeval tval[2]; + + (void)gettimeofday(&tval[0], NULL); + tval[1].tv_sec = mtime; + tval[1].tv_usec = 0; + (*closefunc)(fout); + fout = NULL; + + if (utimes(savefile, tval) == -1) { + fprintf(ttyout, + "Can't change modification time to %s", + asctime(localtime(&mtime))); + } + } + if (bytes > 0) + ptransfer(0); + bytes = 0; + + rval = 0; + goto cleanup_fetch_url; + + improper: + warnx("Improper response from `%s'", host); + + cleanup_fetch_url: + if (oldintr) + (void)xsignal(SIGINT, oldintr); + if (oldintp) + (void)xsignal(SIGPIPE, oldintp); + if (fin != NULL) + fclose(fin); + else if (s != -1) + close(s); + if (closefunc != NULL && fout != NULL) + (*closefunc)(fout); + if (res0) + freeaddrinfo(res0); + FREEPTR(savefile); + FREEPTR(user); + FREEPTR(pass); + FREEPTR(host); + FREEPTR(port); + FREEPTR(path); + FREEPTR(decodedpath); + FREEPTR(puser); + FREEPTR(ppass); + FREEPTR(buf); + FREEPTR(auth); + FREEPTR(location); + FREEPTR(message); + return (rval); +} + +/* + * Abort a HTTP retrieval + */ +void +aborthttp(int notused) +{ + char msgbuf[100]; + int len; + + sigint_raised = 1; + alarmtimer(0); + len = strlcpy(msgbuf, "\nHTTP fetch aborted.\n", sizeof(msgbuf)); + write(fileno(ttyout), msgbuf, len); + siglongjmp(httpabort, 1); +} + +/* + * Retrieve ftp URL or classic ftp argument using FTP. + * Returns 1 on failure, 0 on completed xfer, -1 if ftp connection + * is still open (e.g, ftp xfer with trailing /) + */ +static int +fetch_ftp(const char *url) +{ + char *cp, *xargv[5], rempath[MAXPATHLEN]; + char *host, *path, *dir, *file, *user, *pass; + char *port; + int dirhasglob, filehasglob, oautologin, rval, type, xargc; + in_port_t portnum; + url_t urltype; + + host = path = dir = file = user = pass = NULL; + port = NULL; + rval = 1; + type = TYPE_I; + + if (STRNEQUAL(url, FTP_URL)) { + if ((parse_url(url, "URL", &urltype, &user, &pass, + &host, &port, &portnum, &path) == -1) || + (user != NULL && *user == '\0') || + EMPTYSTRING(host)) { + warnx("Invalid URL `%s'", url); + goto cleanup_fetch_ftp; + } + /* + * Note: Don't url_decode(path) here. We need to keep the + * distinction between "/" and "%2F" until later. + */ + + /* check for trailing ';type=[aid]' */ + if (! EMPTYSTRING(path) && (cp = strrchr(path, ';')) != NULL) { + if (strcasecmp(cp, ";type=a") == 0) + type = TYPE_A; + else if (strcasecmp(cp, ";type=i") == 0) + type = TYPE_I; + else if (strcasecmp(cp, ";type=d") == 0) { + warnx( + "Directory listing via a URL is not supported"); + goto cleanup_fetch_ftp; + } else { + warnx("Invalid suffix `%s' in URL `%s'", cp, + url); + goto cleanup_fetch_ftp; + } + *cp = 0; + } + } else { /* classic style `[user@]host:[file]' */ + urltype = CLASSIC_URL_T; + host = xstrdup(url); + cp = strchr(host, '@'); + if (cp != NULL) { + *cp = '\0'; + user = host; + anonftp = 0; /* disable anonftp */ + host = xstrdup(cp + 1); + } + cp = strchr(host, ':'); + if (cp != NULL) { + *cp = '\0'; + path = xstrdup(cp + 1); + } + } + if (EMPTYSTRING(host)) + goto cleanup_fetch_ftp; + + /* Extract the file and (if present) directory name. */ + dir = path; + if (! EMPTYSTRING(dir)) { + /* + * If we are dealing with classic `[user@]host:[path]' syntax, + * then a path of the form `/file' (resulting from input of the + * form `host:/file') means that we should do "CWD /" before + * retrieving the file. So we set dir="/" and file="file". + * + * But if we are dealing with URLs like `ftp://host/path' then + * a path of the form `/file' (resulting from a URL of the form + * `ftp://host//file') means that we should do `CWD ' (with an + * empty argument) before retrieving the file. So we set + * dir="" and file="file". + * + * If the path does not contain / at all, we set dir=NULL. + * (We get a path without any slashes if we are dealing with + * classic `[user@]host:[file]' or URL `ftp://host/file'.) + * + * In all other cases, we set dir to a string that does not + * include the final '/' that separates the dir part from the + * file part of the path. (This will be the empty string if + * and only if we are dealing with a path of the form `/file' + * resulting from an URL of the form `ftp://host//file'.) + */ + cp = strrchr(dir, '/'); + if (cp == dir && urltype == CLASSIC_URL_T) { + file = cp + 1; + dir = "/"; + } else if (cp != NULL) { + *cp++ = '\0'; + file = cp; + } else { + file = dir; + dir = NULL; + } + } else + dir = NULL; + if (urltype == FTP_URL_T && file != NULL) { + url_decode(file); + /* but still don't url_decode(dir) */ + } + if (debug) + fprintf(ttyout, + "fetch_ftp: user `%s' pass `%s' host %s port %s " + "path `%s' dir `%s' file `%s'\n", + user ? user : "<null>", pass ? pass : "<null>", + host ? host : "<null>", port ? port : "<null>", + path ? path : "<null>", + dir ? dir : "<null>", file ? file : "<null>"); + + dirhasglob = filehasglob = 0; + if (doglob && urltype == CLASSIC_URL_T) { + if (! EMPTYSTRING(dir) && strpbrk(dir, "*?[]{}") != NULL) + dirhasglob = 1; + if (! EMPTYSTRING(file) && strpbrk(file, "*?[]{}") != NULL) + filehasglob = 1; + } + + /* Set up the connection */ + if (connected) + disconnect(0, NULL); + xargv[0] = (char *)getprogname(); /* XXX discards const */ + xargv[1] = host; + xargv[2] = NULL; + xargc = 2; + if (port) { + xargv[2] = port; + xargv[3] = NULL; + xargc = 3; + } + oautologin = autologin; + /* don't autologin in setpeer(), use ftp_login() below */ + autologin = 0; + setpeer(xargc, xargv); + autologin = oautologin; + if ((connected == 0) || + (connected == 1 && !ftp_login(host, user, pass))) { + warnx("Can't connect or login to host `%s'", host); + goto cleanup_fetch_ftp; + } + + switch (type) { + case TYPE_A: + setascii(1, xargv); + break; + case TYPE_I: + setbinary(1, xargv); + break; + default: + errx(1, "fetch_ftp: unknown transfer type %d", type); + } + + /* + * Change directories, if necessary. + * + * Note: don't use EMPTYSTRING(dir) below, because + * dir=="" means something different from dir==NULL. + */ + if (dir != NULL && !dirhasglob) { + char *nextpart; + + /* + * If we are dealing with a classic `[user@]host:[path]' + * (urltype is CLASSIC_URL_T) then we have a raw directory + * name (not encoded in any way) and we can change + * directories in one step. + * + * If we are dealing with an `ftp://host/path' URL + * (urltype is FTP_URL_T), then RFC 1738 says we need to + * send a separate CWD command for each unescaped "/" + * in the path, and we have to interpret %hex escaping + * *after* we find the slashes. It's possible to get + * empty components here, (from multiple adjacent + * slashes in the path) and RFC 1738 says that we should + * still do `CWD ' (with a null argument) in such cases. + * + * Many ftp servers don't support `CWD ', so if there's an + * error performing that command, bail out with a descriptive + * message. + * + * Examples: + * + * host: dir="", urltype=CLASSIC_URL_T + * logged in (to default directory) + * host:file dir=NULL, urltype=CLASSIC_URL_T + * "RETR file" + * host:dir/ dir="dir", urltype=CLASSIC_URL_T + * "CWD dir", logged in + * ftp://host/ dir="", urltype=FTP_URL_T + * logged in (to default directory) + * ftp://host/dir/ dir="dir", urltype=FTP_URL_T + * "CWD dir", logged in + * ftp://host/file dir=NULL, urltype=FTP_URL_T + * "RETR file" + * ftp://host//file dir="", urltype=FTP_URL_T + * "CWD ", "RETR file" + * host:/file dir="/", urltype=CLASSIC_URL_T + * "CWD /", "RETR file" + * ftp://host///file dir="/", urltype=FTP_URL_T + * "CWD ", "CWD ", "RETR file" + * ftp://host/%2F/file dir="%2F", urltype=FTP_URL_T + * "CWD /", "RETR file" + * ftp://host/foo/file dir="foo", urltype=FTP_URL_T + * "CWD foo", "RETR file" + * ftp://host/foo/bar/file dir="foo/bar" + * "CWD foo", "CWD bar", "RETR file" + * ftp://host//foo/bar/file dir="/foo/bar" + * "CWD ", "CWD foo", "CWD bar", "RETR file" + * ftp://host/foo//bar/file dir="foo//bar" + * "CWD foo", "CWD ", "CWD bar", "RETR file" + * ftp://host/%2F/foo/bar/file dir="%2F/foo/bar" + * "CWD /", "CWD foo", "CWD bar", "RETR file" + * ftp://host/%2Ffoo/bar/file dir="%2Ffoo/bar" + * "CWD /foo", "CWD bar", "RETR file" + * ftp://host/%2Ffoo%2Fbar/file dir="%2Ffoo%2Fbar" + * "CWD /foo/bar", "RETR file" + * ftp://host/%2Ffoo%2Fbar%2Ffile dir=NULL + * "RETR /foo/bar/file" + * + * Note that we don't need `dir' after this point. + */ + do { + if (urltype == FTP_URL_T) { + nextpart = strchr(dir, '/'); + if (nextpart) { + *nextpart = '\0'; + nextpart++; + } + url_decode(dir); + } else + nextpart = NULL; + if (debug) + fprintf(ttyout, "dir `%s', nextpart `%s'\n", + dir ? dir : "<null>", + nextpart ? nextpart : "<null>"); + if (urltype == FTP_URL_T || *dir != '\0') { + xargv[0] = "cd"; + xargv[1] = dir; + xargv[2] = NULL; + dirchange = 0; + cd(2, xargv); + if (! dirchange) { + if (*dir == '\0' && code == 500) + fprintf(stderr, +"\n" +"ftp: The `CWD ' command (without a directory), which is required by\n" +" RFC 1738 to support the empty directory in the URL pathname (`//'),\n" +" conflicts with the server's conformance to RFC 959.\n" +" Try the same URL without the `//' in the URL pathname.\n" +"\n"); + goto cleanup_fetch_ftp; + } + } + dir = nextpart; + } while (dir != NULL); + } + + if (EMPTYSTRING(file)) { + rval = -1; + goto cleanup_fetch_ftp; + } + + if (dirhasglob) { + (void)strlcpy(rempath, dir, sizeof(rempath)); + (void)strlcat(rempath, "/", sizeof(rempath)); + (void)strlcat(rempath, file, sizeof(rempath)); + file = rempath; + } + + /* Fetch the file(s). */ + xargc = 2; + xargv[0] = "get"; + xargv[1] = file; + xargv[2] = NULL; + if (dirhasglob || filehasglob) { + int ointeractive; + + ointeractive = interactive; + interactive = 0; + if (restartautofetch) + xargv[0] = "mreget"; + else + xargv[0] = "mget"; + mget(xargc, xargv); + interactive = ointeractive; + } else { + if (outfile == NULL) { + cp = strrchr(file, '/'); /* find savefile */ + if (cp != NULL) + outfile = cp + 1; + else + outfile = file; + } + xargv[2] = (char *)outfile; + xargv[3] = NULL; + xargc++; + if (restartautofetch) + reget(xargc, xargv); + else + get(xargc, xargv); + } + + if ((code / 100) == COMPLETE) + rval = 0; + + cleanup_fetch_ftp: + FREEPTR(host); + FREEPTR(path); + FREEPTR(user); + FREEPTR(pass); + return (rval); +} + +/* + * Retrieve the given file to outfile. + * Supports arguments of the form: + * "host:path", "ftp://host/path" if $ftpproxy, call fetch_url() else + * call fetch_ftp() + * "http://host/path" call fetch_url() to use HTTP + * "file:///path" call fetch_url() to copy + * "about:..." print a message + * + * Returns 1 on failure, 0 on completed xfer, -1 if ftp connection + * is still open (e.g, ftp xfer with trailing /) + */ +static int +go_fetch(const char *url) +{ + char *proxy; + +#ifndef NO_ABOUT + /* + * Check for about:* + */ + if (STRNEQUAL(url, ABOUT_URL)) { + url += sizeof(ABOUT_URL) -1; + if (strcasecmp(url, "ftp") == 0 || + strcasecmp(url, "tnftp") == 0) { + fputs( +"This version of ftp has been enhanced by Luke Mewburn <lukem@NetBSD.org>\n" +"for the NetBSD project. Execute `man ftp' for more details.\n", ttyout); + } else if (strcasecmp(url, "lukem") == 0) { + fputs( +"Luke Mewburn is the author of most of the enhancements in this ftp client.\n" +"Please email feedback to <lukem@NetBSD.org>.\n", ttyout); + } else if (strcasecmp(url, "netbsd") == 0) { + fputs( +"NetBSD is a freely available and redistributable UNIX-like operating system.\n" +"For more information, see http://www.NetBSD.org/\n", ttyout); + } else if (strcasecmp(url, "version") == 0) { + fprintf(ttyout, "Version: %s %s%s\n", + FTP_PRODUCT, FTP_VERSION, +#ifdef INET6 + "" +#else + " (-IPv6)" +#endif + ); + } else { + fprintf(ttyout, "`%s' is an interesting topic.\n", url); + } + fputs("\n", ttyout); + return (0); + } +#endif + + /* + * Check for file:// and http:// URLs. + */ + if (STRNEQUAL(url, HTTP_URL) || STRNEQUAL(url, FILE_URL)) + return (fetch_url(url, NULL, NULL, NULL)); + + /* + * Try FTP URL-style and host:file arguments next. + * If ftpproxy is set with an FTP URL, use fetch_url() + * Othewise, use fetch_ftp(). + */ + proxy = getoptionvalue("ftp_proxy"); + if (!EMPTYSTRING(proxy) && STRNEQUAL(url, FTP_URL)) + return (fetch_url(url, NULL, NULL, NULL)); + + return (fetch_ftp(url)); +} + +/* + * Retrieve multiple files from the command line, + * calling go_fetch() for each file. + * + * If an ftp path has a trailing "/", the path will be cd-ed into and + * the connection remains open, and the function will return -1 + * (to indicate the connection is alive). + * If an error occurs the return value will be the offset+1 in + * argv[] of the file that caused a problem (i.e, argv[x] + * returns x+1) + * Otherwise, 0 is returned if all files retrieved successfully. + */ +int +auto_fetch(int argc, char *argv[]) +{ + volatile int argpos; + int rval; + + argpos = 0; + + if (sigsetjmp(toplevel, 1)) { + if (connected) + disconnect(0, NULL); + if (rval > 0) + rval = argpos + 1; + return (rval); + } + (void)xsignal(SIGINT, intr); + (void)xsignal(SIGPIPE, lostpeer); + + /* + * Loop through as long as there's files to fetch. + */ + for (rval = 0; (rval == 0) && (argpos < argc); argpos++) { + if (strchr(argv[argpos], ':') == NULL) + break; + redirect_loop = 0; + if (!anonftp) + anonftp = 2; /* Handle "automatic" transfers. */ + rval = go_fetch(argv[argpos]); + if (outfile != NULL && strcmp(outfile, "-") != 0 + && outfile[0] != '|') + outfile = NULL; + if (rval > 0) + rval = argpos + 1; + } + + if (connected && rval != -1) + disconnect(0, NULL); + return (rval); +} + + +int +auto_put(int argc, char **argv, const char *uploadserver) +{ + char *uargv[4], *path, *pathsep; + int uargc, rval, len; + + uargc = 0; + uargv[uargc++] = "mput"; + uargv[uargc++] = argv[0]; + uargv[2] = uargv[3] = NULL; + pathsep = NULL; + rval = 1; + + if (debug) + fprintf(ttyout, "auto_put: target `%s'\n", uploadserver); + + path = xstrdup(uploadserver); + len = strlen(path); + if (path[len - 1] != '/' && path[len - 1] != ':') { + /* + * make sure we always pass a directory to auto_fetch + */ + if (argc > 1) { /* more than one file to upload */ + int len; + + len = strlen(uploadserver) + 2; /* path + "/" + "\0" */ + free(path); + path = (char *)xmalloc(len); + (void)strlcpy(path, uploadserver, len); + (void)strlcat(path, "/", len); + } else { /* single file to upload */ + uargv[0] = "put"; + pathsep = strrchr(path, '/'); + if (pathsep == NULL) { + pathsep = strrchr(path, ':'); + if (pathsep == NULL) { + warnx("Invalid URL `%s'", path); + goto cleanup_auto_put; + } + pathsep++; + uargv[2] = xstrdup(pathsep); + pathsep[0] = '/'; + } else + uargv[2] = xstrdup(pathsep + 1); + pathsep[1] = '\0'; + uargc++; + } + } + if (debug) + fprintf(ttyout, "auto_put: URL `%s' argv[2] `%s'\n", + path, uargv[2] ? uargv[2] : "<null>"); + + /* connect and cwd */ + rval = auto_fetch(1, &path); + free(path); + if(rval >= 0) + goto cleanup_auto_put; + + /* XXX : is this the best way? */ + if (uargc == 3) { + uargv[1] = argv[0]; + put(uargc, uargv); + goto cleanup_auto_put; + } + + for(; argv[0] != NULL; argv++) { + uargv[1] = argv[0]; + mput(uargc, uargv); + } + rval = 0; + + cleanup_auto_put: + FREEPTR(uargv[2]); + return (rval); +} diff --git a/contrib/tnftp/src/ftp.1 b/contrib/tnftp/src/ftp.1 new file mode 100644 index 0000000..917980f --- /dev/null +++ b/contrib/tnftp/src/ftp.1 @@ -0,0 +1,2357 @@ +.\" $NetBSD: ftp.1,v 1.109 2005/02/20 20:54:01 wiz Exp $ +.\" +.\" Copyright (c) 1996-2004 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Luke Mewburn. +.\" +.\" 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 NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" +.\" Copyright (c) 1985, 1989, 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. 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 January 15, 2005 +.Dt FTP 1 +.Os +.Sh NAME +.Nm ftp +.Nd +Internet file transfer program +.Sh SYNOPSIS +.Nm +.Op Fl 46AadefginpRtvV +.Bk -words +.Op Fl N Ar netrc +.Ek +.Bk -words +.Op Fl o Ar output +.Ek +.Bk -words +.Op Fl P Ar port +.Ek +.Bk -words +.Op Fl q Ar quittime +.Ek +.Bk -words +.Op Fl r Ar retry +.Ek +.Bk -words +.\" [-T dir,max[,inc]] +.Oo +.Fl T Xo +.Sm off +.Ar dir , +.Ar max +.Op , Ar inc +.Sm on +.Xc +.Oc +.Ek +.Bk -words +.\" [[user@]host [port]] +.Oo +.Oo Ar user Ns Li \&@ Oc Ns Ar host +.Op Ar port +.Oc +.Ek +.Bk -words +.\" [[user@]host:[path][/]] +.Sm off +.Oo +.Op Ar user Li \&@ +.Ar host Li \&: +.Op Ar path +.Op Li / +.Oc +.Sm on +.Ek +.Bk -words +.\" [file:///path] +.Sm off +.Oo +.Li file:/// Ar path +.Oc +.Sm on +.Ek +.Bk -words +.\" [ftp://[user[:password]@]host[:port]/path[/]] +.Sm off +.Oo +.Li ftp:// +.Oo Ar user +.Op Li \&: Ar password +.Li \&@ Oc +.Ar host Oo Li \&: Ar port Oc +.Li / Ar path +.Op Li / +.Op Li ;type= Ar X +.Oc +.Sm on +.Ek +.Bk -words +.\" [http://[user[:password]@]host[:port]/path] +.Sm off +.Oo +.Li http:// +.Oo Ar user +.Op Li \&: Ar password +.Li \&@ Oc +.Ar host Oo Li \&: Ar port Oc +.Li / Ar path +.Oc +.Sm on +.Ek +.Op Ar \&.\&.\&. +.Nm +.Bk -words +.Fl u Ar URL Ar file +.Ek +.Op Ar \&.\&.\&. +.Sh DESCRIPTION +.Nm +is the user interface to the Internet standard File Transfer Protocol. +The program allows a user to transfer files to and from a +remote network site. +.Pp +The last five arguments will fetch a file using the +.Tn FTP +or +.Tn HTTP +protocols, or by direct copying, into the current directory. +This is ideal for scripts. +Refer to +.Sx AUTO-FETCHING FILES +below for more information. +.Pp +Options may be specified at the command line, or to the +command interpreter. +.Bl -tag -width "port " +.It Fl 4 +Forces +.Nm +to only use IPv4 addresses. +.It Fl 6 +Forces +.Nm +to only use IPv6 addresses. +.It Fl A +Force active mode ftp. +By default, +.Nm +will try to use passive mode ftp and fall back to active mode +if passive is not supported by the server. +This option causes +.Nm +to always use an active connection. +It is only useful for connecting to very old servers that do not +implement passive mode properly. +.It Fl a +Causes +.Nm +to bypass normal login procedure, and use an anonymous login instead. +.It Fl d +Enables debugging. +.It Fl e +Disables command line editing. +This is useful for Emacs ange-ftp mode. +.It Fl f +Forces a cache reload for transfers that go through the +.Tn FTP +or +.Tn HTTP +proxies. +.It Fl g +Disables file name globbing. +.It Fl i +Turns off interactive prompting during +multiple file transfers. +.It Fl n +Restrains +.Nm +from attempting +.Dq auto-login +upon initial connection for non auto-fetch transfers. +If auto-login is enabled, +.Nm +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 +will prompt for the remote machine login name (default is the user +identity on the local machine), and, if necessary, prompt for a password +and an account with which to login. +To override the auto-login for auto-fetch transfers, specify the +username (and optionally, password) as appropriate. +.It Fl N Ar netrc +Use +.Ar netrc +instead of +.Pa ~/.netrc . +Refer to +.Sx THE .netrc FILE +for more information. +.It Fl o Ar output +When auto-fetching files, save the contents in +.Ar output . +.Ar output +is parsed according to the +.Sx FILE NAMING CONVENTIONS +below. +If +.Ar output +is not +.Sq - +or doesn't start with +.Sq \&| , +then only the first file specified will be retrieved into +.Ar output ; +all other files will be retrieved into the basename of their +remote name. +.It Fl p +Enable passive mode operation for use behind connection filtering firewalls. +This option has been deprecated as +.Nm +now tries to use passive mode by default, falling back to active mode +if the server does not support passive connections. +.It Fl P Ar port +Sets the port number to +.Ar port . +.It Fl r Ar wait +Retry the connection attempt if it failed, pausing for +.Ar wait +seconds. +.It Fl q Ar quittime +Quit if the connection has stalled for +.Ar quittime +seconds. +.It Fl R +Restart all non-proxied auto-fetches. +.It Fl t +Enables packet tracing. +.It Xo +.Fl T +.Sm off +.Ar direction , +.Ar maximum +.Op , Ar increment +.Sm on +.Xc +Set the maximum transfer rate for +.Ar direction +to +.Ar maximum +bytes/second, +and if specified, the increment to +.Ar increment +bytes/second. +Refer to +.Ic rate +for more information. +.It Fl u Ar URL file Op \&.\&.\&. +Upload files on the command line to +.Ar URL +where +.Ar URL +is one of the ftp URL types as supported by auto-fetch +(with an optional target filename for single file uploads), and +.Ar file +is one or more local files to be uploaded. +.It Fl v +Enable +.Ic verbose +and +.Ic progress . +This is the default if output is to a terminal (and in the case of +.Ic progress , +.Nm +is the foreground process). +Forces +.Nm +to show all responses from the remote server, as well +as report on data transfer statistics. +.It Fl V +Disable +.Ic verbose +and +.Ic progress , +overriding the default of enabled when output is to a terminal. +.El +.Pp +The client host with which +.Nm +is to communicate may be specified on the command line. +If this is done, +.Nm +will immediately attempt to establish a connection to an +.Tn FTP +server on that host; otherwise, +.Nm +will enter its command interpreter and await instructions +from the user. +When +.Nm +is awaiting commands from the user the prompt +.Ql ftp\*[Gt] +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 get , +.Ic mget +and +.Ic mput +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 remote-file +Change the permission modes of the file +.Ar remote-file +on the remote +system to +.Ar mode . +.It Ic close +Terminate the +.Tn FTP +session with the remote server, and +return to the command interpreter. +Any defined macros are erased. +.It Ic \&cr +Toggle carriage return stripping during +ascii type file retrieval. +Records are denoted by a carriage return/linefeed sequence +during ascii type file transfer. +When +.Ic \&cr +is on (the default), carriage returns are stripped from this +sequence to conform with the +.Ux +single linefeed record +delimiter. +Records on +.Pf non\- Ns Ux +remote systems may contain single linefeeds; +when an ascii type transfer is made, these linefeeds may be +distinguished from a record delimiter only when +.Ic \&cr +is off. +.It Ic 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 +prints each command sent to the remote machine, preceded +by the string +.Ql \-\-\*[Gt] +.It Ic delete Ar remote-file +Delete the file +.Ar remote-file +on the remote machine. +.It Ic dir Op Ar remote-path Op Ar local-file +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 . +If +.Ar remote-path +is left unspecified, the current working directory is used. +If interactive prompting is on, +.Nm +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic dir +output. +If no local file is specified, or if +.Ar local-file +is +.Sq Fl , +the output is sent to the terminal. +.It Ic disconnect +A synonym for +.Ic close . +.It Ic edit +Toggle command line editing, and context sensitive command and file +completion. +This is automatically enabled if input is from a terminal, and +disabled otherwise. +.It Ic epsv4 +Toggle the use of the extended +.Dv EPSV +and +.Dv EPRT +commands on IPv4 connections; first try +.Dv EPSV / +.Dv EPRT , +and then +.Dv PASV / +.Dv PORT . +This is enabled by default. +If an extended command fails then this option will be temporarily +disabled for the duration of the current connection, or until +.Ic epsv4 +is executed again. +.It Ic exit +A synonym for +.Ic bye . +.It Ic features +Display what features the remote server supports (using the +.Dv FEAT +command). +.It Ic fget Ar localfile +Retrieve the files listed in +.Ar localfile , +which has one line per filename. +.It Ic form Ar format +Set the file transfer +.Ic form +to +.Ar format . +The default (and only supported) +format is +.Dq non-print . +.It Ic ftp Ar host Op Ar port +A synonym for +.Ic open . +.It Ic gate Op Ar host Op Ar port +Toggle gate-ftp mode, which used to connect through the +TIS FWTK and Gauntlet ftp proxies. +This will not be permitted if the gate-ftp server hasn't been set +(either explicitly by the user, or from the +.Ev FTPSERVER +environment variable). +If +.Ar host +is given, +then gate-ftp mode will be enabled, and the gate-ftp server will be set to +.Ar host . +If +.Ar port +is also given, that will be used as the port to connect to on the +gate-ftp server. +.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 , +.Ic mput , +and +.Ic mreget . +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 , +.Ic mget , +and +.Ic mreget , +each remote file name is expanded +separately on the remote machine and the lists are not merged. +Expansion of a directory name is likely to be +different from expansion of the name of an ordinary file: +the exact result depends on the foreign operating system and ftp server, +and can be previewed by doing +.Ql mls remote-files \- +Note: +.Ic mget , +.Ic mput +and +.Ic mreget +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 Op Ar size +Toggle hash-sign (``#'') printing for each data block +transferred. +The size of a data block defaults to 1024 bytes. +This can be changed by specifying +.Ar size +in bytes. +Enabling +.Ic hash +disables +.Ic progress . +.It Ic help Op Ar command +Print an informative message about the meaning of +.Ar command . +If no argument is given, +.Nm +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 image +A synonym for +.Ic binary . +.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 Ic less Ar file +A synonym for +.Ic page . +.It Ic lpage Ar local-file +Display +.Ar local-file +with the program specified by the +.Ic "set pager" +option. +.It Ic lpwd +Print the working directory on the local machine. +.It Ic \&ls Op Ar remote-path Op Ar local-file +A synonym for +.Ic dir . +.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 +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 ls , +except multiple remote files may be specified, +and the +.Ar local-file +must be specified. +If interactive prompting is on, +.Nm +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic mls +output. +.It Ic mlsd Op Ar remote-path +Display the contents of +.Ar remote-path +(which should default to the current directory if not given) +in a machine-parsable form, using +.Dv MLSD . +The format of display can be changed with +.Sq "remopts mlst ..." . +.It Ic mlst Op Ar remote-path +Display the details about +.Ar remote-path +(which should default to the current directory if not given) +in a machine-parsable form, using +.Dv MLST . +The format of display can be changed with +.Sq "remopts mlst ..." . +.It Ic mode Ar mode-name +Set the file transfer +.Ic mode +to +.Ar mode-name . +The default (and only supported) +mode is +.Dq stream . +.It Ic modtime Ar remote-file +Show the last modification time of the file on the remote machine. +.It Ic more Ar file +A synonym for +.Ic page . +.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 mreget Ar remote-files +As per +.Ic mget , +but performs a +.Ic reget +instead of +.Ic get . +.It Ic msend Ar local-files +A synonym for +.Ic mput . +.It Ic newer Ar remote-file Op Ar local-file +Get the file only if the modification time of the remote file is more +recent that the file on the current system. +If the file does not +exist on the current system, the remote file is considered +.Ic newer . +Otherwise, this command is identical to +.Ar get . +.It Ic nlist Op Ar remote-path Op Ar local-file +A synonym for +.Ic ls . +.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/ *$//" \*[Gt] $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 +will attempt to contact an +.Tn FTP +server at that port. +If the +.Ic "set auto-login" +option is on (default), +.Nm +will also attempt to automatically log the user in to +the +.Tn FTP +server (see below). +.It Ic page Ar file +Retrieve +.Ic file +and display with the program specified by the +.Ic "set pager" +option. +.It Ic passive Op Cm auto +Toggle passive mode (if no arguments are given). +If +.Cm auto +is given, act as if +.Ev FTPMODE +is set to +.Sq auto . +If passive mode is turned on (default), +.Nm +will send a +.Dv PASV +command for all data connections instead of a +.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 +through a gateway router or host that controls the directionality of +traffic. +(Note that though +.Tn FTP +servers are required to support the +.Dv PASV +command by +.Li RFC 1123 , +some do not.) +.It Ic pdir Op Ar remote-path +Perform +.Ic dir +.Op Ar remote-path , +and display the result with the program specified by the +.Ic "set pager" +option. +.It Ic pls Op Ar remote-path +Perform +.Ic ls +.Op Ar remote-path , +and display the result with the program specified by the +.Ic "set pager" +option. +.It Ic pmlsd Op Ar remote-path +Perform +.Ic mlsd +.Op Ar remote-path , +and display the result with the program specified by the +.Ic "set pager" +option. +.It Ic preserve +Toggle preservation of modification times on retrieved files. +.It Ic progress +Toggle display of transfer progress bar. +The progress bar will be disabled for a transfer that has +.Ar local-file +as +.Sq Fl +or a command that starts with +.Sq \&| . +Refer to +.Sx FILE NAMING CONVENTIONS +for more information. +Enabling +.Ic progress +disables +.Ic hash . +.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. +.Pp +When prompting is on, the following commands are available at a prompt: +.Bl -tag -width 2n -offset indent +.It Cm a +Answer +.Sq yes +to the current file, and automatically answer +.Sq yes +to any remaining files for the current command. +.It Cm n +Answer +.Sq no , +and do not transfer the file. +.It Cm p +Answer +.Sq yes +to the current file, and turn off prompt mode +(as is +.Dq prompt off +had been given). +.It Cm q +Terminate the current operation. +.It Cm y +Answer +.Sq yes , +and transfer the file. +.It Cm \&? +Display a help message. +.El +.Pp +Any other response will answer +.Sq yes +to the current file. +.It Ic proxy Ar ftp-command +Execute an ftp command on a secondary control connection. +This command allows simultaneous connection to two remote +.Tn 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 +.Tn 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 +.Tn 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 Xo +.Ic rate Ar direction +.Op Ar maximum Op Ar increment +.Xc +Throttle the maximum transfer rate to +.Ar maximum +bytes/second. +If +.Ar maximum +is 0, disable the throttle. +.Pp +.Ar direction +may be one of: +.Bl -tag -width "all" -offset indent -compact +.It Cm all +Both directions. +.It Cm get +Incoming transfers. +.It Cm put +Outgoing transfers. +.El +.Pp +.Ar maximum +can be modified on the fly by +.Ar increment +bytes (default: 1024) each time a given signal is received: +.B +.Bl -tag -width "SIGUSR1" -offset indent +.It Dv SIGUSR1 +Increment +.Ar maximum +by +.Ar increment +bytes. +.It Dv SIGUSR2 +Decrement +.Ar maximum +by +.Ar increment +bytes. +The result must be a positive number. +.El +.Pp +If +.Ar maximum +is not supplied, the current throttle rates are displayed. +.Pp +Note: +.Ic rate +is not yet implemented for ascii mode transfers. +.It Ic rcvbuf Ar size +Set the size of the socket receive buffer to +.Ar size . +.It Ic recv Ar remote-file Op Ar local-file +A synonym for +.Ic get . +.It Ic reget Ar remote-file Op Ar local-file +.Ic reget +acts like +.Ic 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 remopts Ar command Op Ar command-options +Set options on the remote +.Tn FTP +server for +.Ar command +to +.Ar command-options +(whose absence is handled on a command-specific basis). +Remote +.Tn FTP +commands known to support options include: +.Sq MLST +(used for +.Dv MLSD +and +.Dv MLST ) . +.It Ic rename Op Ar from Op Ar to +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 +.Tn FTP +server. +Resynchronization may be necessary following a violation of the +.Tn 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 rhelp 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 rmdir Ar directory-name +Delete a directory on the remote machine. +.It Ic rstatus Op Ar remote-file +With no arguments, show status of remote machine. +If +.Ar remote-file +is specified, show status of +.Ar remote-file +on 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 +.Ic put . +.It Ic sendport +Toggle the use of +.Dv PORT +commands. +By default, +.Nm +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 +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 set Op Ar option Ar value +Set +.Ar option +to +.Ar value . +If +.Ar option +and +.Ar value +are not given, display all of the options and their values. +The currently supported options are: +.Bl -tag -width "http_proxy" -offset indent +.It Cm anonpass +Defaults to +.Ev $FTPANONPASS +.It Cm ftp_proxy +Defaults to +.Ev $ftp_proxy . +.It Cm http_proxy +Defaults to +.Ev $http_proxy . +.It Cm no_proxy +Defaults to +.Ev $no_proxy . +.It Cm pager +Defaults to +.Ev $PAGER . +.It Cm prompt +Defaults to +.Ev $FTPPROMPT . +.It Cm rprompt +Defaults to +.Ev $FTPRPROMPT . +.El +.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 remote-file +Return size of +.Ar remote-file +on remote machine. +.It Ic sndbuf Ar size +Set the size of the socket send buffer to +.Ar size . +.It Ic status +Show the current status of +.Nm ftp . +.It Ic struct Ar struct-name +Set the file transfer +.Ar structure +to +.Ar struct-name . +The default (and only supported) +structure is +.Dq file . +.It Ic sunique +Toggle storing of files on remote machine under unique file names. +The remote +.Tn FTP +server must support +.Tn 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 throttle +A synonym for +.Ic rate . +.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 Ic unset Ar option +Unset +.Ar option . +Refer to +.Ic set +for more information. +.It Ic usage Ar command +Print the usage message for +.Ar command . +.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 +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 +is invoked with +.Dq auto-login +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 xferbuf Ar size +Set the size of the socket send and receive buffers to +.Ar size . +.It Ic \&? Op Ar command +A synonym for +.Ic help . +.El +.Pp +Command arguments which have embedded spaces may be quoted with +quote `"' marks. +.Pp +Commands which toggle settings can take an explicit +.Ic on +or +.Ic off +argument to force the setting appropriately. +.Pp +Commands which take a byte count as an argument +(e.g., +.Ic hash , +.Ic rate , +and +.Ic xferbuf ) +support an optional suffix on the argument which changes the +interpretation of the argument. +Supported suffixes are: +.Bl -tag -width 3n -offset indent -compact +.It Li b +Causes no modification. +(Optional) +.It Li k +Kilo; multiply the argument by 1024 +.It Li m +Mega; multiply the argument by 1048576 +.It Li g +Giga; multiply the argument by 1073741824 +.El +.Pp +If +.Nm +receives a +.Dv SIGINFO +(see the +.Dq status +argument of +.Xr stty 1 ) +or +.Dv SIGQUIT +signal whilst a transfer is in progress, the current transfer rate +statistics will be written to the standard error output, in the +same format as the standard completion message. +.Sh AUTO-FETCHING FILES +In addition to standard commands, this version of +.Nm +supports an auto-fetch feature. +To enable auto-fetch, simply pass the list of hostnames/files +on the command line. +.Pp +The following formats are valid syntax for an auto-fetch element: +.Bl -tag -width "FOO " +.\" [user@]host:[path][/] +.It Xo +.Sm off +.Op Ar user Li \&@ +.Ar host Li \&: +.Op Ar path +.Op Li / +.Sm on +.Xc +.Dq Classic +.Tn FTP +format. +.Pp +If +.Ar path +contains a glob character and globbing is enabled, +(see +.Ic glob ) , +then the equivalent of +.Ql mget path +is performed. +.Pp +If the directory component of +.Ar path +contains no globbing characters, +it is stored locally with the name basename (see +.Xr basename 1 ) +of +.Ic path , +in the current directory. +Otherwise, the full remote name is used as the local name, +relative to the local root directory. +.\" ftp://[user[:password]@]host[:port]/path[/][;type=X] +.It Xo +.Sm off +.Li ftp:// +.Oo Ar user +.Op Li \&: Ar password +.Li \&@ Oc +.Ar host Oo Li \&: Ar port Oc +.Li / Ar path +.Op Li / +.Op Li ;type= Ar X +.Sm on +.Xc +An +.Tn FTP +URL, retrieved using the +.Tn FTP +protocol if +.Ic "set ftp_proxy" +isn't defined. +Otherwise, transfer the URL using +.Tn HTTP +via the proxy defined in +.Ic "set ftp_proxy" . +If +.Ic "set ftp_proxy" +isn't defined and +.Ar user +is given, login as +.Ar user . +In this case, use +.Ar password +if supplied, otherwise prompt the user for one. +.Pp +If a suffix of +.Sq ;type=A +or +.Sq ;type=I +is supplied, then the transfer type will take place as +ascii or binary (respectively). +The default transfer type is binary. +.Pp +In order to be compliant with +.Li RFC 1738 , +.Nm +interprets the +.Ar path +part of an +.Dq ftp:// +auto-fetch URL as follows: +.Bl -bullet +.It +The +.Sq Li / +immediately after the +.Ar host Ns Oo Li \&: Ns Ar port Oc +is interpreted as a separator before the +.Ar path , +and not as part of the +.Ar path +itself. +.It +The +.Ar path +is interpreted as a +.So Li / Sc Ns -separated +list of name components. +For all but the last such component, +.Nm +performs the equivalent of a +.Ic cd +command. +For the last path component, +.Nm +performs the equivalent of a +.Ic get +command. +.It +Empty name components, +which result from +.Sq Li // +within the +.Ar path , +or from an extra +.Sq Li / +at the beginning of the +.Ar path , +will cause the equivalent of a +.Ic cd +command without a directory name. +This is unlikely to be useful. +.It +Any +.Sq Li \&% Ns Ar XX +codes +(per +.Li RFC 1738 ) +within the path components are decoded, with +.Ar XX +representing a character code in hexadecimal. +This decoding takes place after the +.Ar path +has been split into components, +but before each component is used in the equivalent of a +.Ic cd +or +.Ic get +command. +Some often-used codes are +.Sq Li \&%2F +(which represents +.Sq Li / ) +and +.Sq Li \&%7E +(which represents +.Sq Li ~ ) . +.El +.Pp +The above interpretation has the following consequences: +.Bl -bullet +.It +The path is interpreted relative to the +default login directory of the specified user or of the +.Sq anonymous +user. +If the +.Pa / +directory is required, use a leading path of +.Dq %2F . +If a user's home directory is required (and the remote server supports +the syntax), use a leading path of +.Dq %7Euser/ . +For example, to retrieve +.Pa /etc/motd +from +.Sq localhost +as the user +.Sq myname +with the password +.Sq mypass , +use +.Dq ftp://myname:mypass@localhost/%2fetc/motd +.It +The exact +.Ic cd +and +.Ic get +commands can be controlled by careful choice of +where to use +.Sq / +and where to use +.Sq %2F +(or +.Sq %2f ) . +For example, the following URLs correspond to the +equivalents of the indicated commands: +.Bl -tag -width "ftp://host/%2Fdir1%2Fdir2%2Ffile" +.It ftp://host/dir1/dir2/file +.Dq "cd dir1" , +.Dq "cd dir2" , +.Dq "get file" . +.It ftp://host/%2Fdir1/dir2/file +.Dq "cd /dir1" , +.Dq "cd dir2" , +.Dq "get file" . +.It ftp://host/dir1%2Fdir2/file +.Dq "cd dir1/dir2" , +.Dq "get file" . +.It ftp://host/%2Fdir1%2Fdir2/file +.Dq "cd /dir1/dir2" , +.Dq "get file" . +.It ftp://host/dir1%2Fdir2%2Ffile +.Dq "get dir1/dir2/file" . +.It ftp://host/%2Fdir1%2Fdir2%2Ffile +.Dq "get /dir1/dir2/file" . +.El +.It +You must have appropriate access permission for each of the +intermediate directories that is used in the equivalent of a +.Ic cd +command. +.El +.\" http://[user[:password]@]host[:port]/path +.It Xo +.Sm off +.Li http:// +.Oo Ar user +.Op Li \&: Ar password +.Li \&@ Oc +.Ar host Oo Li \&: Ar port Oc +.Li / Ar path +.Sm on +.Xc +An +.Tn HTTP +URL, retrieved using the +.Tn HTTP +protocol. +If +.Ic "set http_proxy" +is defined, it is used as a URL to an +.Tn HTTP +proxy server. +If +.Tn HTTP +authorization is required to retrieve +.Ar path , +and +.Sq user +(and optionally +.Sq password ) +is in the URL, use them for the first attempt to authenticate. +.\" file:///path +.It Xo +.Sm off +.Li file:/// Ar path +.Sm on +.Xc +A local URL, copied from +.Pa / Ns Ar path +on the local host. +.El +.Pp +Unless noted otherwise above, and +.Fl o Ar output +is not given, the file is stored in the current directory as the +.Xr basename 1 +of +.Ar path . +Note that if a +.Tn HTTP +redirect is received, the fetch is retried using the new target URL +supplied by the server, with a corresponding new +.Ar path . +Using an explicit +.Fl o Ar output +is recommended, to avoid writing to unexpected file names. +.Pp +If a classic format or an +.Tn FTP +URL format has a trailing +.Sq / +or an empty +.Ar path +component, then +.Nm +will connect to the site and +.Ic cd +to the directory given as the path, and leave the user in interactive +mode ready for further input. +This will not work if +.Ic "set ftp_proxy" +is being used. +.Pp +Direct +.Tn HTTP +transfers use HTTP 1.1. +Proxied +.Tn FTP +and +.Tn HTTP +transfers use HTTP 1.0. +.Pp +If +.Fl R +is given, all auto-fetches that don't go via the +.Tn FTP +or +.Tn HTTP +proxies will be restarted. +For +.Tn FTP , +this is implemented by using +.Nm reget +instead of +.Nm get . +For +.Tn HTTP , +this is implemented by using the +.Sq "Range: bytes=" +.Tn "HTTP/1.1" +directive. +.Pp +If WWW or proxy WWW authentication is required, you will be prompted +to enter a username and password to authenticate with. +.Pp +When specifying IPv6 numeric addresses in a URL, you need to +surround the address in square brackets. +E.g.: +.Dq ftp://[::1]:21/ . +This is because colons are used in IPv6 numeric address as well as +being the separator for the port number. +.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 an +.Tn 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, the prompt will not appear until the remote server has completed +sending the requested file. +.Pp +If the terminal interrupt key sequence is used whilst +.Nm +is awaiting a reply from the remote server for the ABOR processing, +then the connection will be closed. +This is different from the traditional behaviour (which ignores the +terminal interrupt during this phase), but is considered more useful. +.Sh FILE NAMING CONVENTIONS +Files specified as arguments to +.Nm +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 +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. +.Dq Qq Li \&| ls\ \-lt . +A particularly +useful example of this mechanism is: +.Dq Li dir \&"\&" \&|more . +.It +Failing the above checks, if ``globbing'' is enabled, +local file names are expanded +according to the rules used in the +.Xr csh 1 ; +c.f. the +.Ic glob +command. +If the +.Nm +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 +.Tn FTP +specification specifies many parameters which may affect a file transfer. +The +.Ic type +may be one of +.Dq ascii , +.Dq image +(binary), +.Dq ebcdic , +and +.Dq local byte size +(for +.Tn PDP Ns -10's +and +.Tn PDP Ns -20's +mostly). +.Nm +supports the ascii and image types of file transfer, +plus local byte size 8 for +.Ic tenex +mode transfers. +.Pp +.Nm +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, +unless overridden with the +.Fl N Ar netrc +option, or specified in the +.Ev NETRC +environment variable. +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 +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 an automatic anonymous +.Tn 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 +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 +.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 blank 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. +For example, +.Bd -literal -offset indent +default +macdef init +epsv4 off +.Ed +.Pp +followed by a blank line. +.El +.Sh COMMAND LINE EDITING +.Nm +supports interactive command line editing, via the +.Xr editline 3 +library. +It is enabled with the +.Ic edit +command, and is enabled by default if input is from a tty. +Previous lines can be recalled and edited with the arrow keys, +and other GNU Emacs-style editing keys may be used as well. +.Pp +The +.Xr editline 3 +library is configured with a +.Pa .editrc +file - refer to +.Xr editrc 5 +for more information. +.Pp +An extra key binding is available to +.Nm +to provide context sensitive command and filename completion +(including remote file completion). +To use this, bind a key to the +.Xr editline 3 +command +.Ic ftp-complete . +By default, this is bound to the TAB key. +.Sh COMMAND LINE PROMPT +By default, +.Nm +displays a command line prompt of +.Dq "ftp\*[Gt] " +to the user. +This can be changed with the +.Ic "set prompt" +command. +.Pp +A prompt can be displayed on the right side of the screen (after the +command input) with the +.Ic "set rprompt" +command. +.Pp +The following formatting sequences are replaced by the given +information: +.Bl -tag -width "%% " -offset indent +.It Li \&%/ +The current remote working directory. +.\" %c[[0]n], %.[[0]n] +.It Xo +.Sm off +.Li \&%c +.Op Oo Li 0 Oc Ar n Ns , +.Li \&%. +.Op Oo Li 0 Oc Ar n +.Sm on +.Xc +The trailing component of the current remote working directory, or +.Em n +trailing components if a digit +.Em n +is given. +If +.Em n +begins with +.Sq 0 , +the number of skipped components precede the trailing component(s) in +the format +.\" ``/<number>trailing'' +.Do +.Sm off +.Li / Li \*[Lt] Va number Li \*[Gt] +.Va trailing +.Sm on +.Dc +(for +.Sq \&%c ) +or +.\" ``...trailing'' +.Dq Li \&... Ns Va trailing +(for +.Sq \&%. ) . +.It Li \&%M +The remote host name. +.It Li \&%m +The remote host name, up to the first +.Sq \&. . +.It Li \&%n +The remote user name. +.It Li \&%% +A single +.Sq % . +.El +.Sh ENVIRONMENT +.Nm +uses the following environment variables. +.Bl -tag -width "FTPSERVERPORT" +.It Ev FTPANONPASS +Password to send in an anonymous +.Tn FTP +transfer. +Defaults to +.Dq Li `whoami`@ . +.It Ev FTPMODE +Overrides the default operation mode. +Support values are: +.Bl -tag -width "passive" +.It Cm active +active mode +.Tn FTP +only +.It Cm auto +automatic determination of passive or active (this is the default) +.It Cm gate +gate-ftp mode +.It Cm passive +passive mode +.Tn FTP +only +.El +.It Ev FTPPROMPT +Command-line prompt to use. +Defaults to +.Dq "ftp\*[Gt] " . +Refer to +.Sx COMMAND LINE PROMPT +for more information. +.It Ev FTPRPROMPT +Command-line right side prompt to use. +Defaults to +.Dq "" . +Refer to +.Sx COMMAND LINE PROMPT +for more information. +.It Ev FTPSERVER +Host to use as gate-ftp server when +.Ic gate +is enabled. +.It Ev FTPSERVERPORT +Port to use when connecting to gate-ftp server when +.Ic gate +is enabled. +Default is port returned by a +.Fn getservbyname +lookup of +.Dq ftpgate/tcp . +.It Ev FTPUSERAGENT +The value to send for the +.Tn HTTP +User-Agent +header. +.It Ev HOME +For default location of a +.Pa .netrc +file, if one exists. +.It Ev NETRC +An alternate location of the +.Pa .netrc +file. +.It Ev PAGER +Used by various commands to display files. +Defaults to +.Xr more 1 +if empty or not set. +.It Ev SHELL +For default shell. +.It Ev ftp_proxy +URL of +.Tn FTP +proxy to use when making +.Tn FTP +URL requests +(if not defined, use the standard +.Tn FTP +protocol). +.Pp +See +.Ev http_proxy +for further notes about proxy use. +.It Ev http_proxy +URL of +.Tn HTTP +proxy to use when making +.Tn HTTP +URL requests. +If proxy authentication is required and there is a username and +password in this URL, they will automatically be used in the first +attempt to authenticate to the proxy. +.Pp +If +.Dq unsafe +URL characters are required in the username or password +(for example +.Sq @ +or +.Sq / ) , +encode them with +.Li RFC 1738 +.Sq Li \&% Ns Ar XX +encoding. +.Pp +Note that the use of a username and password in +.Ev ftp_proxy +and +.Ev http_proxy +may be incompatible with other programs that use it +(such as +.Xr lynx 1 ) . +.Pp +.Em NOTE : +this is not used for interactive sessions, only for command-line +fetches. +.It Ev no_proxy +A space or comma separated list of hosts (or domains) for which +proxying is not to be used. +Each entry may have an optional trailing ":port", which restricts +the matching to connections to that port. +.El +.Sh EXTENDED PASSIVE MODE AND FIREWALLS +Some firewall configurations do not allow +.Nm +to use extended passive mode. +If you find that even a simple +.Ic ls +appears to hang after printing a message such as this: +.Pp +.Dl 229 Entering Extended Passive Mode (|||58551|) +.Pp +then you will need to disable extended passive mode with +.Ic epsv4 off . +See the above section +.Sx The .netrc File +for an example of how to make this automatic. +.Sh SEE ALSO +.Xr getservbyname 3 , +.Xr editrc 5 , +.Xr services 5 , +.Xr ftpd 8 +.Sh STANDARDS +.Nm +attempts to be compliant with +.Li RFC 959 , +.Li RFC 1123 , +.Li RFC 1738 , +.Li RFC 2068 , +.Li RFC 2389 , +.Li RFC 2428 , +.Li RFC 2732 , +and +.Cm draft-ietf-ftpext-mlst-11 . +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Pp +Various features such as command line editing, context sensitive +command and file completion, dynamic progress bar, automatic +fetching of files and URLs, modification time preservation, +transfer rate throttling, configurable command line prompt, +and other enhancements over the standard +.Bx +.Nm +were implemented in +.Nx 1.3 +and later releases +by +.An Luke Mewburn +.Aq lukem@NetBSD.org . +.Pp +IPv6 support was added by the WIDE/KAME project +(but may not be present in all non-NetBSD versions of this program, depending +if the operating system supports IPv6 in a similar manner to KAME). +.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. +.Pp +.Nm +assumes that all IPv4 mapped addresses +.Po +IPv6 addresses with a form like +.Li ::ffff:10.1.1.1 +.Pc +indicate IPv4 destinations which can be handled by +.Dv AF_INET +sockets. +However, in certain IPv6 network configurations, this assumption is not true. +In such an environment, IPv4 mapped addresses must be passed to +.Dv AF_INET6 +sockets directly. +For example, if your site uses a SIIT translator for IPv6-to-IPv4 translation, +.Nm +is unable to support your configuration. diff --git a/contrib/tnftp/src/ftp.c b/contrib/tnftp/src/ftp.c new file mode 100644 index 0000000..dae6131 --- /dev/null +++ b/contrib/tnftp/src/ftp.c @@ -0,0 +1,2171 @@ +/* $NetBSD: ftp.c,v 1.132 2005/05/14 15:26:43 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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. + */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; +#else +__RCSID("$NetBSD: ftp.c,v 1.132 2005/05/14 15:26:43 lukem Exp $"); +#endif +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <arpa/inet.h> +#include <arpa/ftp.h> +#include <arpa/telnet.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <stdarg.h> + +#include "ftp_var.h" + +volatile sig_atomic_t abrtflag; +volatile sig_atomic_t timeoutflag; + +sigjmp_buf ptabort; +int ptabflg; +int ptflag = 0; +char pasv[BUFSIZ]; /* passive port for proxy data connection */ + +static int empty(FILE *, FILE *, int); + +struct sockinet { + union sockunion { + struct sockaddr_in su_sin; +#ifdef INET6 + struct sockaddr_in6 su_sin6; +#endif + } si_su; +#if !HAVE_SOCKADDR_SA_LEN + int si_len; +#endif +}; + +#if !HAVE_SOCKADDR_SA_LEN +# define su_len si_len +#else +# define su_len si_su.su_sin.sin_len +#endif +#define su_family si_su.su_sin.sin_family +#define su_port si_su.su_sin.sin_port + +struct sockinet myctladdr, hisctladdr, data_addr; + +char * +hookup(char *host, char *port) +{ + int s = -1, error, portnum; + struct addrinfo hints, *res, *res0; + char hbuf[MAXHOSTNAMELEN]; + static char hostnamebuf[MAXHOSTNAMELEN]; + char *cause = "unknown"; + socklen_t len; + int on = 1; + + memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); + memset((char *)&myctladdr, 0, sizeof (myctladdr)); + memset(&hints, 0, sizeof(hints)); + portnum = parseport(port, FTP_PORT); + hints.ai_flags = AI_CANONNAME; + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + error = getaddrinfo(host, NULL, &hints, &res0); + if (error) { + warnx("%s", gai_strerror(error)); + code = -1; + return (0); + } + + if (res0->ai_canonname) + (void)strlcpy(hostnamebuf, res0->ai_canonname, + sizeof(hostnamebuf)); + else + (void)strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); + hostname = hostnamebuf; + + for (res = res0; res; res = res->ai_next) { + /* + * make sure that ai_addr is NOT an IPv4 mapped address. + * IPv4 mapped address complicates too many things in FTP + * protocol handling, as FTP protocol is defined differently + * between IPv4 and IPv6. + * + * This may not be the best way to handle this situation, + * since the semantics of IPv4 mapped address is defined in + * the kernel. There are configurations where we should use + * IPv4 mapped address as native IPv6 address, not as + * "an IPv6 address that embeds IPv4 address" (namely, SIIT). + * + * More complete solution would be to have an additional + * getsockopt to grab "real" peername/sockname. "real" + * peername/sockname will be AF_INET if IPv4 mapped address + * is used to embed IPv4 address, and will be AF_INET6 if + * we use it as native. What a mess! + */ + ai_unmapped(res); +#if 0 /*old behavior*/ + if (res != res0) /* not on the first address */ +#else + if (res0->ai_next) /* if we have multiple possibilities */ +#endif + { + if (getnameinfo(res->ai_addr, res->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) + strlcpy(hbuf, "?", sizeof(hbuf)); + fprintf(ttyout, "Trying %s...\n", hbuf); + } + ((struct sockaddr_in *)res->ai_addr)->sin_port = htons(portnum); + s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); + if (s < 0) { + cause = "socket"; + continue; + } + error = xconnect(s, res->ai_addr, res->ai_addrlen); + if (error) { + /* this "if" clause is to prevent print warning twice */ + if (res->ai_next) { + if (getnameinfo(res->ai_addr, res->ai_addrlen, + hbuf, sizeof(hbuf), NULL, 0, + NI_NUMERICHOST)) + strlcpy(hbuf, "?", sizeof(hbuf)); + warn("connect to address %s", hbuf); + } + cause = "connect"; + close(s); + s = -1; + continue; + } + + /* finally we got one */ + break; + } + if (s < 0) { + warn("%s", cause); + code = -1; + freeaddrinfo(res0); + return 0; + } + memcpy(&hisctladdr.si_su, res->ai_addr, res->ai_addrlen); + hisctladdr.su_len = res->ai_addrlen; + freeaddrinfo(res0); + res0 = res = NULL; + + len = hisctladdr.su_len; + if (getsockname(s, (struct sockaddr *)&myctladdr.si_su, &len) == -1) { + warn("getsockname"); + code = -1; + goto bad; + } + myctladdr.su_len = len; + +#ifdef IPTOS_LOWDELAY + if (hisctladdr.su_family == AF_INET) { + int tos = IPTOS_LOWDELAY; + if (setsockopt(s, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(tos)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", + "IPTOS_LOWDELAY"); + } + } +#endif + cin = fdopen(s, "r"); + cout = fdopen(s, "w"); + if (cin == NULL || cout == NULL) { + warnx("fdopen failed."); + if (cin) + (void)fclose(cin); + if (cout) + (void)fclose(cout); + code = -1; + goto bad; + } + if (verbose) + fprintf(ttyout, "Connected to %s.\n", hostname); + if (getreply(0) > 2) { /* read startup message from server */ + if (cin) + (void)fclose(cin); + if (cout) + (void)fclose(cout); + code = -1; + goto bad; + } + + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, + (void *)&on, sizeof(on)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", "SO_OOBINLINE"); + } + + return (hostname); + bad: + (void)close(s); + return (NULL); +} + +void +cmdabort(int notused) +{ + int oerrno = errno; + + sigint_raised = 1; + alarmtimer(0); + if (fromatty) + write(fileno(ttyout), "\n", 1); + abrtflag++; + if (ptflag) + siglongjmp(ptabort, 1); + errno = oerrno; +} + +void +cmdtimeout(int notused) +{ + int oerrno = errno; + + alarmtimer(0); + if (fromatty) + write(fileno(ttyout), "\n", 1); + timeoutflag++; + if (ptflag) + siglongjmp(ptabort, 1); + errno = oerrno; +} + +/*VARARGS*/ +int +command(const char *fmt, ...) +{ + va_list ap; + int r; + sigfunc oldsigint; + + if (debug) { + fputs("---> ", ttyout); + va_start(ap, fmt); + if (strncmp("PASS ", fmt, 5) == 0) + fputs("PASS XXXX", ttyout); + else if (strncmp("ACCT ", fmt, 5) == 0) + fputs("ACCT XXXX", ttyout); + else + vfprintf(ttyout, fmt, ap); + va_end(ap); + putc('\n', ttyout); + } + if (cout == NULL) { + warnx("No control connection for command."); + code = -1; + return (0); + } + + abrtflag = 0; + + oldsigint = xsignal(SIGINT, cmdabort); + + va_start(ap, fmt); + vfprintf(cout, fmt, ap); + va_end(ap); + fputs("\r\n", cout); + (void)fflush(cout); + cpend = 1; + r = getreply(!strcmp(fmt, "QUIT")); + if (abrtflag && oldsigint != SIG_IGN) + (*oldsigint)(SIGINT); + (void)xsignal(SIGINT, oldsigint); + return (r); +} + +int +getreply(int expecteof) +{ + char current_line[BUFSIZ]; /* last line of previous reply */ + int c, n, line; + int dig; + int originalcode = 0, continuation = 0; + sigfunc oldsigint, oldsigalrm; + int pflag = 0; + char *cp, *pt = pasv; + + abrtflag = 0; + timeoutflag = 0; + + oldsigint = xsignal(SIGINT, cmdabort); + oldsigalrm = xsignal(SIGALRM, cmdtimeout); + + for (line = 0 ;; line++) { + dig = n = code = 0; + cp = current_line; + while (alarmtimer(60),((c = getc(cin)) != '\n')) { + if (c == IAC) { /* handle telnet commands */ + switch (c = getc(cin)) { + case WILL: + case WONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, DONT, c); + (void)fflush(cout); + break; + case DO: + case DONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, WONT, c); + (void)fflush(cout); + break; + default: + break; + } + continue; + } + dig++; + if (c == EOF) { + /* + * these will get trashed by pswitch() + * in lostpeer() + */ + int reply_timeoutflag = timeoutflag; + int reply_abrtflag = abrtflag; + + alarmtimer(0); + if (expecteof && feof(cin)) { + (void)xsignal(SIGINT, oldsigint); + (void)xsignal(SIGALRM, oldsigalrm); + code = 221; + return (0); + } + cpend = 0; + lostpeer(0); + if (verbose) { + if (reply_timeoutflag) + fputs( + "421 Service not available, remote server timed out. Connection closed\n", + ttyout); + else if (reply_abrtflag) + fputs( + "421 Service not available, user interrupt. Connection closed.\n", + ttyout); + else + fputs( + "421 Service not available, remote server has closed connection.\n", + ttyout); + (void)fflush(ttyout); + } + code = 421; + (void)xsignal(SIGINT, oldsigint); + (void)xsignal(SIGALRM, oldsigalrm); + return (4); + } + if (c != '\r' && (verbose > 0 || + ((verbose > -1 && n == '5' && dig > 4) && + (((!n && c < '5') || (n && n < '5')) + || !retry_connect)))) { + if (proxflag && + (dig == 1 || (dig == 5 && verbose == 0))) + fprintf(ttyout, "%s:", hostname); + (void)putc(c, ttyout); + } + if (dig < 4 && isdigit(c)) + code = code * 10 + (c - '0'); + if (!pflag && (code == 227 || code == 228)) + pflag = 1; + else if (!pflag && code == 229) + pflag = 100; + if (dig > 4 && pflag == 1 && isdigit(c)) + pflag = 2; + if (pflag == 2) { + if (c != '\r' && c != ')') { + if (pt < &pasv[sizeof(pasv) - 1]) + *pt++ = c; + } else { + *pt = '\0'; + pflag = 3; + } + } + if (pflag == 100 && c == '(') + pflag = 2; + if (dig == 4 && c == '-') { + if (continuation) + code = 0; + continuation++; + } + if (n == 0) + n = c; + if (cp < ¤t_line[sizeof(current_line) - 1]) + *cp++ = c; + } + if (verbose > 0 || ((verbose > -1 && n == '5') && + (n < '5' || !retry_connect))) { + (void)putc(c, ttyout); + (void)fflush (ttyout); + } + if (cp[-1] == '\r') + cp[-1] = '\0'; + *cp = '\0'; + if (line == 0) + (void)strlcpy(reply_string, current_line, + sizeof(reply_string)); + if (line > 0 && code == 0 && reply_callback != NULL) + (*reply_callback)(current_line); + if (continuation && code != originalcode) { + if (originalcode == 0) + originalcode = code; + continue; + } + if (n != '1') + cpend = 0; + alarmtimer(0); + (void)xsignal(SIGINT, oldsigint); + (void)xsignal(SIGALRM, oldsigalrm); + if (code == 421 || originalcode == 421) + lostpeer(0); + if (abrtflag && oldsigint != cmdabort && oldsigint != SIG_IGN) + (*oldsigint)(SIGINT); + if (timeoutflag && oldsigalrm != cmdtimeout && + oldsigalrm != SIG_IGN) + (*oldsigalrm)(SIGINT); + return (n - '0'); + } +} + +static int +empty(FILE *cin, FILE *din, int sec) +{ + int nr, nfd; + struct pollfd pfd[2]; + + nfd = 0; + if (cin) { + pfd[nfd].fd = fileno(cin); + pfd[nfd++].events = POLLIN; + } + + if (din) { + pfd[nfd].fd = fileno(din); + pfd[nfd++].events = POLLIN; + } + + if ((nr = xpoll(pfd, nfd, sec * 1000)) <= 0) + return nr; + + nr = 0; + nfd = 0; + if (cin) + nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0; + if (din) + nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0; + return nr; +} + +sigjmp_buf xferabort; + +void +abortxfer(int notused) +{ + char msgbuf[100]; + size_t len; + + sigint_raised = 1; + alarmtimer(0); + mflag = 0; + abrtflag = 0; + switch (direction[0]) { + case 'r': + strlcpy(msgbuf, "\nreceive", sizeof(msgbuf)); + break; + case 's': + strlcpy(msgbuf, "\nsend", sizeof(msgbuf)); + break; + default: + errx(1, "abortxfer called with unknown direction `%s'", + direction); + } + len = strlcat(msgbuf, " aborted. Waiting for remote to finish abort.\n", + sizeof(msgbuf)); + write(fileno(ttyout), msgbuf, len); + siglongjmp(xferabort, 1); +} + +void +sendrequest(const char *cmd, const char *local, const char *remote, + int printnames) +{ + struct stat st; + int c, d; + FILE *fin, *dout; + int (*closefunc)(FILE *); + sigfunc oldintr, oldintp; + volatile off_t hashbytes; + char *lmode, *bufp; + static size_t bufsize; + static char *buf; + int oprogress; + +#ifdef __GNUC__ /* to shut up gcc warnings */ + (void)&fin; + (void)&dout; + (void)&closefunc; + (void)&oldintr; + (void)&oldintp; + (void)&lmode; +#endif + + hashbytes = mark; + direction = "sent"; + dout = NULL; + bytes = 0; + filesize = -1; + oprogress = progress; + if (verbose && printnames) { + if (local && *local != '-') + fprintf(ttyout, "local: %s ", local); + if (remote) + fprintf(ttyout, "remote: %s\n", remote); + } + if (proxy) { + proxtrans(cmd, local, remote); + return; + } + if (curtype != type) + changetype(type, 0); + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + lmode = "w"; + if (sigsetjmp(xferabort, 1)) { + while (cpend) + (void)getreply(0); + code = -1; + goto cleanupsend; + } + (void)xsignal(SIGQUIT, psummary); + oldintr = xsignal(SIGINT, abortxfer); + if (strcmp(local, "-") == 0) { + fin = stdin; + progress = 0; + } else if (*local == '|') { + oldintp = xsignal(SIGPIPE, SIG_IGN); + fin = popen(local + 1, "r"); + if (fin == NULL) { + warn("%s", local + 1); + code = -1; + goto cleanupsend; + } + progress = 0; + closefunc = pclose; + } else { + fin = fopen(local, "r"); + if (fin == NULL) { + warn("local: %s", local); + code = -1; + goto cleanupsend; + } + closefunc = fclose; + if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) { + fprintf(ttyout, "%s: not a plain file.\n", local); + code = -1; + goto cleanupsend; + } + filesize = st.st_size; + } + if (initconn()) { + code = -1; + goto cleanupsend; + } + if (sigsetjmp(xferabort, 1)) + goto abort; + + if (restart_point && + (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + int rc; + + rc = -1; + switch (curtype) { + case TYPE_A: + rc = fseeko(fin, 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); + goto cleanupsend; + } + if (command("REST " LLF, (LLT)restart_point) != CONTINUE) + goto cleanupsend; + lmode = "r+"; + } + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) + goto cleanupsend; + } else { + if (command("%s", cmd) != PRELIM) + goto cleanupsend; + } + dirchange = 1; + dout = dataconn(lmode); + if (dout == NULL) + goto abort; + + if (sndbuf_size > bufsize) { + if (buf) + (void)free(buf); + bufsize = sndbuf_size; + buf = xmalloc(bufsize); + } + + progressmeter(-1); + oldintp = xsignal(SIGPIPE, SIG_IGN); + + switch (curtype) { + + case TYPE_I: + case TYPE_L: + if (rate_put) { /* rate limited */ + while (1) { + struct timeval then, now, td; + off_t bufrem; + + (void)gettimeofday(&then, NULL); + errno = c = d = 0; + bufrem = rate_put; + while (bufrem > 0) { + if ((c = read(fileno(fin), buf, + MIN(bufsize, bufrem))) <= 0) + goto senddone; + bytes += c; + bufrem -= c; + for (bufp = buf; c > 0; + c -= d, bufp += d) + if ((d = write(fileno(dout), + bufp, c)) <= 0) + break; + if (d < 0) + goto senddone; + if (hash && + (!progress || filesize < 0) ) { + while (bytes >= hashbytes) { + (void)putc('#', ttyout); + hashbytes += mark; + } + (void)fflush(ttyout); + } + } + while (1) { + (void)gettimeofday(&now, NULL); + timersub(&now, &then, &td); + if (td.tv_sec > 0) + break; + usleep(1000000 - td.tv_usec); + } + } + } else { /* simpler/faster; no rate limit */ + while (1) { + errno = c = d = 0; + if ((c = read(fileno(fin), buf, bufsize)) <= 0) + goto senddone; + bytes += c; + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = write(fileno(dout), bufp, c)) + <= 0) + break; + if (d < 0) + goto senddone; + if (hash && (!progress || filesize < 0) ) { + while (bytes >= hashbytes) { + (void)putc('#', ttyout); + hashbytes += mark; + } + (void)fflush(ttyout); + } + } + } + senddone: + if (hash && (!progress || filesize < 0) && bytes > 0) { + if (bytes < mark) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + } + if (c < 0) + warn("local: %s", local); + if (d < 0) { + if (errno != EPIPE) + warn("netout"); + bytes = -1; + } + break; + + case TYPE_A: + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + while (hash && (!progress || filesize < 0) && + (bytes >= hashbytes)) { + (void)putc('#', ttyout); + (void)fflush(ttyout); + hashbytes += mark; + } + if (ferror(dout)) + break; + (void)putc('\r', dout); + bytes++; + } + (void)putc(c, dout); + bytes++; +#if 0 /* this violates RFC */ + if (c == '\r') { + (void)putc('\0', dout); + bytes++; + } +#endif + } + if (hash && (!progress || filesize < 0)) { + if (bytes < hashbytes) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + } + if (ferror(fin)) + warn("local: %s", local); + if (ferror(dout)) { + if (errno != EPIPE) + warn("netout"); + bytes = -1; + } + break; + } + + progressmeter(1); + if (closefunc != NULL) { + (*closefunc)(fin); + fin = NULL; + } + (void)fclose(dout); + dout = NULL; + (void)getreply(0); + if (bytes > 0) + ptransfer(0); + goto cleanupsend; + + abort: + (void)xsignal(SIGINT, oldintr); + oldintr = NULL; + if (!cpend) { + code = -1; + goto cleanupsend; + } + if (data >= 0) { + (void)close(data); + data = -1; + } + if (dout) { + (void)fclose(dout); + dout = NULL; + } + (void)getreply(0); + code = -1; + if (bytes > 0) + ptransfer(0); + + cleanupsend: + if (oldintr) + (void)xsignal(SIGINT, oldintr); + if (oldintp) + (void)xsignal(SIGPIPE, oldintp); + if (data >= 0) { + (void)close(data); + data = -1; + } + if (closefunc != NULL && fin != NULL) + (*closefunc)(fin); + if (dout) + (void)fclose(dout); + progress = oprogress; + restart_point = 0; + bytes = 0; +} + +void +recvrequest(const char *cmd, const char *local, const char *remote, + const char *lmode, int printnames, int ignorespecial) +{ + FILE *fout, *din; + int (*closefunc)(FILE *); + sigfunc oldintr, oldintp; + int c, d; + volatile int is_retr, tcrflag, bare_lfs; + static size_t bufsize; + static char *buf; + volatile off_t hashbytes; + struct stat st; + time_t mtime; + struct timeval tval[2]; + int oprogress; + int opreserve; + +#ifdef __GNUC__ /* to shut up gcc warnings */ + (void)&local; + (void)&fout; + (void)&din; + (void)&closefunc; + (void)&oldintr; + (void)&oldintp; +#endif + + fout = NULL; + din = NULL; + hashbytes = mark; + direction = "received"; + bytes = 0; + bare_lfs = 0; + filesize = -1; + oprogress = progress; + opreserve = preserve; + is_retr = (strcmp(cmd, "RETR") == 0); + if (is_retr && verbose && printnames) { + if (local && (ignorespecial || *local != '-')) + fprintf(ttyout, "local: %s ", local); + if (remote) + fprintf(ttyout, "remote: %s\n", remote); + } + if (proxy && is_retr) { + proxtrans(cmd, local, remote); + return; + } + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + tcrflag = !crflag && is_retr; + if (sigsetjmp(xferabort, 1)) { + while (cpend) + (void)getreply(0); + code = -1; + goto cleanuprecv; + } + (void)xsignal(SIGQUIT, psummary); + oldintr = xsignal(SIGINT, abortxfer); + if (ignorespecial || (strcmp(local, "-") && *local != '|')) { + if (access(local, W_OK) < 0) { + char *dir = strrchr(local, '/'); + + if (errno != ENOENT && errno != EACCES) { + warn("local: %s", local); + code = -1; + goto cleanuprecv; + } + if (dir != NULL) + *dir = 0; + d = access(dir == local ? "/" : + dir ? local : ".", W_OK); + if (dir != NULL) + *dir = '/'; + if (d < 0) { + warn("local: %s", local); + code = -1; + goto cleanuprecv; + } + if (!runique && errno == EACCES && + chmod(local, (S_IRUSR|S_IWUSR)) < 0) { + warn("local: %s", local); + code = -1; + goto cleanuprecv; + } + if (runique && errno == EACCES && + (local = gunique(local)) == NULL) { + code = -1; + goto cleanuprecv; + } + } + else if (runique && (local = gunique(local)) == NULL) { + code = -1; + goto cleanuprecv; + } + } + if (!is_retr) { + if (curtype != TYPE_A) + changetype(TYPE_A, 0); + } else { + if (curtype != type) + changetype(type, 0); + filesize = remotesize(remote, 0); + if (code == 421 || code == -1) + goto cleanuprecv; + } + if (initconn()) { + code = -1; + goto cleanuprecv; + } + if (sigsetjmp(xferabort, 1)) + goto abort; + if (is_retr && restart_point && + command("REST " LLF, (LLT) restart_point) != CONTINUE) + goto cleanuprecv; + if (! EMPTYSTRING(remote)) { + if (command("%s %s", cmd, remote) != PRELIM) + goto cleanuprecv; + } else { + if (command("%s", cmd) != PRELIM) + goto cleanuprecv; + } + din = dataconn("r"); + if (din == NULL) + goto abort; + if (!ignorespecial && strcmp(local, "-") == 0) { + fout = stdout; + progress = 0; + preserve = 0; + } else if (!ignorespecial && *local == '|') { + oldintp = xsignal(SIGPIPE, SIG_IGN); + fout = popen(local + 1, "w"); + if (fout == NULL) { + warn("%s", local+1); + goto abort; + } + progress = 0; + preserve = 0; + closefunc = pclose; + } else { + fout = fopen(local, lmode); + if (fout == NULL) { + warn("local: %s", local); + goto abort; + } + closefunc = fclose; + } + + if (fstat(fileno(fout), &st) != -1 && !S_ISREG(st.st_mode)) { + progress = 0; + preserve = 0; + } + if (rcvbuf_size > bufsize) { + if (buf) + (void)free(buf); + bufsize = rcvbuf_size; + buf = xmalloc(bufsize); + } + + progressmeter(-1); + + switch (curtype) { + + case TYPE_I: + case TYPE_L: + if (is_retr && restart_point && + lseek(fileno(fout), restart_point, SEEK_SET) < 0) { + warn("local: %s", local); + goto cleanuprecv; + } + if (rate_get) { /* rate limiting */ + while (1) { + struct timeval then, now, td; + off_t bufrem; + + (void)gettimeofday(&then, NULL); + errno = c = d = 0; + for (bufrem = rate_get; bufrem > 0; ) { + if ((c = read(fileno(din), buf, + MIN(bufsize, bufrem))) <= 0) + goto recvdone; + bytes += c; + bufrem -=c; + if ((d = write(fileno(fout), buf, c)) + != c) + goto recvdone; + if (hash && + (!progress || filesize < 0)) { + while (bytes >= hashbytes) { + (void)putc('#', ttyout); + hashbytes += mark; + } + (void)fflush(ttyout); + } + } + /* sleep until time is up */ + while (1) { + (void)gettimeofday(&now, NULL); + timersub(&now, &then, &td); + if (td.tv_sec > 0) + break; + usleep(1000000 - td.tv_usec); + } + } + } else { /* faster code (no limiting) */ + while (1) { + errno = c = d = 0; + if ((c = read(fileno(din), buf, bufsize)) <= 0) + goto recvdone; + bytes += c; + if ((d = write(fileno(fout), buf, c)) != c) + goto recvdone; + if (hash && (!progress || filesize < 0)) { + while (bytes >= hashbytes) { + (void)putc('#', ttyout); + hashbytes += mark; + } + (void)fflush(ttyout); + } + } + } + recvdone: + if (hash && (!progress || filesize < 0) && bytes > 0) { + if (bytes < mark) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + } + if (c < 0) { + 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 (is_retr && restart_point) { + int ch; + off_t i; + + if (fseeko(fout, (off_t)0, SEEK_SET) < 0) + goto done; + for (i = 0; i++ < restart_point;) { + if ((ch = getc(fout)) == EOF) + goto done; + if (ch == '\n') + i++; + } + if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) { + done: + warn("local: %s", local); + goto cleanuprecv; + } + } + while ((c = getc(din)) != EOF) { + if (c == '\n') + bare_lfs++; + while (c == '\r') { + while (hash && (!progress || filesize < 0) && + (bytes >= hashbytes)) { + (void)putc('#', ttyout); + (void)fflush(ttyout); + hashbytes += mark; + } + bytes++; + if ((c = getc(din)) != '\n' || tcrflag) { + if (ferror(fout)) + goto break2; + (void)putc('\r', fout); + if (c == '\0') { + bytes++; + goto contin2; + } + if (c == EOF) + goto contin2; + } + } + (void)putc(c, fout); + bytes++; + contin2: ; + } + break2: + if (hash && (!progress || filesize < 0)) { + if (bytes < hashbytes) + (void)putc('#', ttyout); + (void)putc('\n', ttyout); + } + if (ferror(din)) { + if (errno != EPIPE) + warn("netin"); + bytes = -1; + } + if (ferror(fout)) + warn("local: %s", local); + break; + } + + progressmeter(1); + if (closefunc != NULL) { + (*closefunc)(fout); + fout = NULL; + } + (void)fclose(din); + din = NULL; + (void)getreply(0); + if (bare_lfs) { + fprintf(ttyout, + "WARNING! %d bare linefeeds received in ASCII mode.\n", + bare_lfs); + fputs("File may not have transferred correctly.\n", ttyout); + } + if (bytes >= 0 && is_retr) { + if (bytes > 0) + ptransfer(0); + if (preserve && (closefunc == fclose)) { + mtime = remotemodtime(remote, 0); + if (mtime != -1) { + (void)gettimeofday(&tval[0], NULL); + tval[1].tv_sec = mtime; + tval[1].tv_usec = 0; + if (utimes(local, tval) == -1) { + fprintf(ttyout, + "Can't change modification time on %s to %s", + local, asctime(localtime(&mtime))); + } + } + } + } + goto cleanuprecv; + + abort: + /* + * abort using RFC 959 recommended IP,SYNC sequence + */ + if (! sigsetjmp(xferabort, 1)) { + /* this is the first call */ + (void)xsignal(SIGINT, abort_squared); + if (!cpend) { + code = -1; + goto cleanuprecv; + } + abort_remote(din); + } + code = -1; + if (bytes > 0) + ptransfer(0); + + cleanuprecv: + if (oldintr) + (void)xsignal(SIGINT, oldintr); + if (oldintp) + (void)xsignal(SIGPIPE, oldintp); + if (data >= 0) { + (void)close(data); + data = -1; + } + if (closefunc != NULL && fout != NULL) + (*closefunc)(fout); + if (din) + (void)fclose(din); + progress = oprogress; + preserve = opreserve; + bytes = 0; +} + +/* + * Need to start a listen on the data channel before we send the command, + * otherwise the server's connect may fail. + */ +int +initconn(void) +{ + char *p, *a; + int result, tmpno = 0; + int on = 1; + int error; + u_int addr[16], port[2]; + u_int af, hal, pal; + socklen_t len; + char *pasvcmd = NULL; + +#ifdef INET6 + if (myctladdr.su_family == AF_INET6 && debug && + (IN6_IS_ADDR_LINKLOCAL(&myctladdr.si_su.su_sin6.sin6_addr) || + IN6_IS_ADDR_SITELOCAL(&myctladdr.si_su.su_sin6.sin6_addr))) { + warnx("use of scoped address can be troublesome"); + } +#endif + reinit: + if (passivemode) { + data_addr = myctladdr; + data = socket(data_addr.su_family, SOCK_STREAM, 0); + if (data < 0) { + warn("socket"); + return (1); + } + if ((options & SO_DEBUG) && + setsockopt(data, SOL_SOCKET, SO_DEBUG, + (void *)&on, sizeof(on)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", "SO_DEBUG"); + } + result = COMPLETE + 1; + switch (data_addr.su_family) { + case AF_INET: + if (epsv4 && !epsv4bad) { + pasvcmd = "EPSV"; + result = command("EPSV"); + if (!connected) + return (1); + /* + * this code is to be friendly with broken + * BSDI ftpd + */ + if (code / 10 == 22 && code != 229) { + fputs( +"wrong server: return code must be 229\n", + ttyout); + result = COMPLETE + 1; + } + if (result != COMPLETE) { + epsv4bad = 1; + if (debug) + fputs( + "disabling epsv4 for this connection\n", + ttyout); + } + } + if (result != COMPLETE) { + pasvcmd = "PASV"; + result = command("PASV"); + if (!connected) + return (1); + } + break; +#ifdef INET6 + case AF_INET6: + pasvcmd = "EPSV"; + result = command("EPSV"); + if (!connected) + return (1); + /* this code is to be friendly with broken BSDI ftpd */ + if (code / 10 == 22 && code != 229) { + fputs( +"wrong server: return code must be 229\n", + ttyout); + result = COMPLETE + 1; + } + if (result != COMPLETE) { + pasvcmd = "LPSV"; + result = command("LPSV"); + } + if (!connected) + return (1); + break; +#endif + default: + result = COMPLETE + 1; + break; + } + if (result != COMPLETE) { + if (activefallback) { + (void)close(data); + data = -1; + passivemode = 0; +#if 0 + activefallback = 0; +#endif + goto reinit; + } + fputs("Passive mode refused.\n", ttyout); + goto bad; + } + +#define pack2(var, off) \ + (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0)) +#define pack4(var, off) \ + (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \ + ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0)) +#define UC(b) (((int)b)&0xff) + + /* + * What we've got at this point is a string of comma separated + * one-byte unsigned integer values, separated by commas. + */ + if (strcmp(pasvcmd, "PASV") == 0) { + if (data_addr.su_family != AF_INET) { + fputs( + "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + if (code / 10 == 22 && code != 227) { + fputs("wrong server: return code must be 227\n", + ttyout); + error = 1; + goto bad; + } + error = sscanf(pasv, "%u,%u,%u,%u,%u,%u", + &addr[0], &addr[1], &addr[2], &addr[3], + &port[0], &port[1]); + if (error != 6) { + fputs( +"Passive mode address scan failure. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + error = 0; + memset(&data_addr, 0, sizeof(data_addr)); + data_addr.su_family = AF_INET; + data_addr.su_len = sizeof(struct sockaddr_in); + data_addr.si_su.su_sin.sin_addr.s_addr = + htonl(pack4(addr, 0)); + data_addr.su_port = htons(pack2(port, 0)); + } else if (strcmp(pasvcmd, "LPSV") == 0) { + if (code / 10 == 22 && code != 228) { + fputs("wrong server: return code must be 228\n", + ttyout); + error = 1; + goto bad; + } + switch (data_addr.su_family) { + case AF_INET: + error = sscanf(pasv, +"%u,%u,%u,%u,%u,%u,%u,%u,%u", + &af, &hal, + &addr[0], &addr[1], &addr[2], &addr[3], + &pal, &port[0], &port[1]); + if (error != 9) { + fputs( +"Passive mode address scan failure. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + if (af != 4 || hal != 4 || pal != 2) { + fputs( +"Passive mode AF mismatch. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + + error = 0; + memset(&data_addr, 0, sizeof(data_addr)); + data_addr.su_family = AF_INET; + data_addr.su_len = sizeof(struct sockaddr_in); + data_addr.si_su.su_sin.sin_addr.s_addr = + htonl(pack4(addr, 0)); + data_addr.su_port = htons(pack2(port, 0)); + break; +#ifdef INET6 + case AF_INET6: + error = sscanf(pasv, +"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", + &af, &hal, + &addr[0], &addr[1], &addr[2], &addr[3], + &addr[4], &addr[5], &addr[6], &addr[7], + &addr[8], &addr[9], &addr[10], + &addr[11], &addr[12], &addr[13], + &addr[14], &addr[15], + &pal, &port[0], &port[1]); + if (error != 21) { + fputs( +"Passive mode address scan failure. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + if (af != 6 || hal != 16 || pal != 2) { + fputs( +"Passive mode AF mismatch. Shouldn't happen!\n", ttyout); + error = 1; + goto bad; + } + + error = 0; + memset(&data_addr, 0, sizeof(data_addr)); + data_addr.su_family = AF_INET6; + data_addr.su_len = sizeof(struct sockaddr_in6); + { + int i; + for (i = 0; i < sizeof(struct in6_addr); i++) { + data_addr.si_su.su_sin6.sin6_addr.s6_addr[i] = + UC(addr[i]); + } + } + data_addr.su_port = htons(pack2(port, 0)); + break; +#endif + default: + error = 1; + } + } else if (strcmp(pasvcmd, "EPSV") == 0) { + char delim[4]; + + port[0] = 0; + if (code / 10 == 22 && code != 229) { + fputs("wrong server: return code must be 229\n", + ttyout); + error = 1; + goto bad; + } + if (sscanf(pasv, "%c%c%c%d%c", &delim[0], + &delim[1], &delim[2], &port[1], + &delim[3]) != 5) { + fputs("parse error!\n", ttyout); + error = 1; + goto bad; + } + if (delim[0] != delim[1] || delim[0] != delim[2] + || delim[0] != delim[3]) { + fputs("parse error!\n", ttyout); + error = 1; + goto bad; + } + data_addr = hisctladdr; + data_addr.su_port = htons(port[1]); + } else + goto bad; + + while (xconnect(data, (struct sockaddr *)&data_addr.si_su, + data_addr.su_len) < 0) { + if (activefallback) { + (void)close(data); + data = -1; + passivemode = 0; +#if 0 + activefallback = 0; +#endif + goto reinit; + } + warn("connect for data channel"); + goto bad; + } +#ifdef IPTOS_THROUGHPUT + if (data_addr.su_family == AF_INET) { + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, + (void *)&on, sizeof(on)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", + "IPTOS_THROUGHPUT"); + } + } +#endif + return (0); + } + + noport: + data_addr = myctladdr; + if (sendport) + data_addr.su_port = 0; /* let system pick one */ + if (data != -1) + (void)close(data); + data = socket(data_addr.su_family, SOCK_STREAM, 0); + if (data < 0) { + warn("socket"); + if (tmpno) + sendport = 1; + return (1); + } + if (!sendport) + if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, + (void *)&on, sizeof(on)) == -1) { + warn("setsockopt %s", "SO_REUSEADDR"); + goto bad; + } + if (bind(data, (struct sockaddr *)&data_addr.si_su, + data_addr.su_len) < 0) { + warn("bind"); + goto bad; + } + if ((options & SO_DEBUG) && + setsockopt(data, SOL_SOCKET, SO_DEBUG, + (void *)&on, sizeof(on)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", "SO_DEBUG"); + } + len = sizeof(data_addr.si_su); + memset((char *)&data_addr, 0, sizeof (data_addr)); + if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) == -1) { + warn("getsockname"); + goto bad; + } + data_addr.su_len = len; + if (xlisten(data, 1) < 0) + warn("listen"); + + if (sendport) { + char hname[NI_MAXHOST], sname[NI_MAXSERV]; + int af; + struct sockinet tmp; + + switch (data_addr.su_family) { + case AF_INET: + if (!epsv4 || epsv4bad) { + result = COMPLETE + 1; + break; + } + /* FALLTHROUGH */ +#ifdef INET6 + case AF_INET6: +#endif + af = (data_addr.su_family == AF_INET) ? 1 : 2; + tmp = data_addr; +#ifdef INET6 + if (tmp.su_family == AF_INET6) + tmp.si_su.su_sin6.sin6_scope_id = 0; +#endif + if (getnameinfo((struct sockaddr *)&tmp.si_su, + tmp.su_len, hname, sizeof(hname), sname, + sizeof(sname), NI_NUMERICHOST | NI_NUMERICSERV)) { + result = ERROR; + } else { + result = command("EPRT |%d|%s|%s|", af, hname, + sname); + if (!connected) + return (1); + if (result != COMPLETE) { + epsv4bad = 1; + if (debug) + fputs( + "disabling epsv4 for this connection\n", + ttyout); + } + } + break; + default: + result = COMPLETE + 1; + break; + } + if (result == COMPLETE) + goto skip_port; + + switch (data_addr.su_family) { + case AF_INET: + a = (char *)&data_addr.si_su.su_sin.sin_addr; + p = (char *)&data_addr.su_port; + result = command("PORT %d,%d,%d,%d,%d,%d", + UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), + UC(p[0]), UC(p[1])); + break; +#ifdef INET6 + case AF_INET6: + a = (char *)&data_addr.si_su.su_sin6.sin6_addr; + p = (char *)&data_addr.su_port; + result = command( + "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", + 6, 16, + UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), + UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), + UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), + UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), + 2, UC(p[0]), UC(p[1])); + break; +#endif + default: + result = COMPLETE + 1; /* xxx */ + } + if (!connected) + return (1); + skip_port: + + if (result == ERROR && sendport == -1) { + sendport = 0; + tmpno = 1; + goto noport; + } + return (result != COMPLETE); + } + if (tmpno) + sendport = 1; +#ifdef IPTOS_THROUGHPUT + if (data_addr.su_family == AF_INET) { + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, + (void *)&on, sizeof(on)) == -1) + if (debug) + warn("setsockopt %s (ignored)", + "IPTOS_THROUGHPUT"); + } +#endif + return (0); + bad: + (void)close(data); + data = -1; + if (tmpno) + sendport = 1; + return (1); +} + +FILE * +dataconn(const char *lmode) +{ + struct sockinet from; + int s, flags, rv, timeout; + struct timeval endtime, now, td; + struct pollfd pfd[1]; + socklen_t fromlen; + + if (passivemode) /* passive data connection */ + return (fdopen(data, lmode)); + + /* active mode data connection */ + + if ((flags = fcntl(data, F_GETFL, 0)) == -1) + goto dataconn_failed; /* get current socket flags */ + if (fcntl(data, F_SETFL, flags | O_NONBLOCK) == -1) + goto dataconn_failed; /* set non-blocking connect */ + + /* NOTE: we now must restore socket flags on successful exit */ + + /* limit time waiting on listening socket */ + pfd[0].fd = data; + pfd[0].events = POLLIN; + (void)gettimeofday(&endtime, NULL); /* determine end time */ + endtime.tv_sec += (quit_time > 0) ? quit_time: 60; + /* without -q, default to 60s */ + do { + (void)gettimeofday(&now, NULL); + timersub(&endtime, &now, &td); + timeout = td.tv_sec * 1000 + td.tv_usec/1000; + if (timeout < 0) + timeout = 0; + rv = xpoll(pfd, 1, timeout); + } while (rv == -1 && errno == EINTR); /* loop until poll ! EINTR */ + if (rv == -1) { + warn("poll waiting before accept"); + goto dataconn_failed; + } + if (rv == 0) { + warn("poll timeout waiting before accept"); + goto dataconn_failed; + } + + /* (non-blocking) accept the connection */ + fromlen = myctladdr.su_len; + do { + s = accept(data, (struct sockaddr *) &from.si_su, &fromlen); + } while (s == -1 && errno == EINTR); /* loop until accept ! EINTR */ + if (s == -1) { + warn("accept"); + goto dataconn_failed; + } + + (void)close(data); + data = s; + if (fcntl(data, F_SETFL, flags) == -1) /* restore socket flags */ + goto dataconn_failed; + +#ifdef IPTOS_THROUGHPUT + if (from.su_family == AF_INET) { + int tos = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(tos)) == -1) { + if (debug) + warn("setsockopt %s (ignored)", + "IPTOS_THROUGHPUT"); + } + } +#endif + return (fdopen(data, lmode)); + + dataconn_failed: + (void)close(data); + data = -1; + return (NULL); +} + +void +psabort(int notused) +{ + int oerrno = errno; + + sigint_raised = 1; + alarmtimer(0); + abrtflag++; + errno = oerrno; +} + +void +pswitch(int flag) +{ + sigfunc oldintr; + static struct comvars { + int connect; + char name[MAXHOSTNAMELEN]; + struct sockinet mctl; + struct sockinet 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 = xsignal(SIGINT, psabort); + if (flag) { + if (proxy) + return; + ip = &tmpstruct; + op = &proxstruct; + proxy++; + } else { + if (!proxy) + return; + ip = &proxstruct; + op = &tmpstruct; + proxy = 0; + } + ip->connect = connected; + connected = op->connect; + if (hostname) + (void)strlcpy(ip->name, hostname, sizeof(ip->name)); + else + ip->name[0] = '\0'; + hostname = op->name; + ip->hctl = hisctladdr; + hisctladdr = op->hctl; + ip->mctl = myctladdr; + myctladdr = op->mctl; + ip->in = cin; + cin = op->in; + ip->out = cout; + cout = op->out; + ip->tpe = type; + type = op->tpe; + ip->curtpe = curtype; + curtype = op->curtpe; + ip->cpnd = cpend; + cpend = op->cpnd; + ip->sunqe = sunique; + sunique = op->sunqe; + ip->runqe = runique; + runique = op->runqe; + ip->mcse = mcase; + mcase = op->mcse; + ip->ntflg = ntflag; + ntflag = op->ntflg; + (void)strlcpy(ip->nti, ntin, sizeof(ip->nti)); + (void)strlcpy(ntin, op->nti, sizeof(ntin)); + (void)strlcpy(ip->nto, ntout, sizeof(ip->nto)); + (void)strlcpy(ntout, op->nto, sizeof(ntout)); + ip->mapflg = mapflag; + mapflag = op->mapflg; + (void)strlcpy(ip->mi, mapin, sizeof(ip->mi)); + (void)strlcpy(mapin, op->mi, sizeof(mapin)); + (void)strlcpy(ip->mo, mapout, sizeof(ip->mo)); + (void)strlcpy(mapout, op->mo, sizeof(mapout)); + (void)xsignal(SIGINT, oldintr); + if (abrtflag) { + abrtflag = 0; + (*oldintr)(SIGINT); + } +} + +void +abortpt(int notused) +{ + + sigint_raised = 1; + alarmtimer(0); + if (fromatty) + write(fileno(ttyout), "\n", 1); + ptabflg++; + mflag = 0; + abrtflag = 0; + siglongjmp(ptabort, 1); +} + +void +proxtrans(const char *cmd, const char *local, const char *remote) +{ + sigfunc oldintr; + int prox_type, nfnd; + volatile int secndflag; + char *cmd2; + +#ifdef __GNUC__ /* to shut up gcc warnings */ + (void)&oldintr; + (void)&cmd2; +#endif + + oldintr = NULL; + secndflag = 0; + 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) { + fputs("proxy server does not support third party transfers.\n", + ttyout); + return; + } + pswitch(0); + if (!connected) { + fputs("No primary connection.\n", ttyout); + pswitch(1); + code = -1; + return; + } + if (curtype != prox_type) + changetype(prox_type, 1); + if (command("PORT %s", pasv) != COMPLETE) { + pswitch(1); + return; + } + if (sigsetjmp(ptabort, 1)) + goto abort; + oldintr = xsignal(SIGINT, abortpt); + if ((restart_point && + (command("REST " LLF, (LLT) restart_point) != CONTINUE)) + || (command("%s %s", cmd, remote) != PRELIM)) { + (void)xsignal(SIGINT, oldintr); + pswitch(1); + return; + } + sleep(2); + pswitch(1); + secndflag++; + if ((restart_point && + (command("REST " LLF, (LLT) restart_point) != CONTINUE)) + || (command("%s %s", cmd2, local) != PRELIM)) + goto abort; + ptflag++; + (void)getreply(0); + pswitch(0); + (void)getreply(0); + (void)xsignal(SIGINT, oldintr); + pswitch(1); + ptflag = 0; + fprintf(ttyout, "local: %s remote: %s\n", local, remote); + return; + abort: + if (sigsetjmp(xferabort, 1)) { + (void)xsignal(SIGINT, oldintr); + return; + } + (void)xsignal(SIGINT, abort_squared); + 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(NULL); + } + pswitch(1); + if (ptabflg) + code = -1; + (void)xsignal(SIGINT, oldintr); + return; + } + if (cpend) + abort_remote(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(NULL); + pswitch(1); + if (ptabflg) + code = -1; + (void)xsignal(SIGINT, oldintr); + return; + } + } + if (cpend) + abort_remote(NULL); + pswitch(!proxy); + if (cpend) { + if ((nfnd = empty(cin, NULL, 10)) <= 0) { + if (nfnd < 0) + warn("abort"); + if (ptabflg) + code = -1; + lostpeer(0); + } + (void)getreply(0); + (void)getreply(0); + } + if (proxy) + pswitch(0); + pswitch(1); + if (ptabflg) + code = -1; + (void)xsignal(SIGINT, oldintr); +} + +void +reset(int argc, char *argv[]) +{ + int nfnd = 1; + + if (argc == 0 && argv != NULL) { + fprintf(ttyout, "usage: %s\n", argv[0]); + code = -1; + return; + } + while (nfnd > 0) { + if ((nfnd = empty(cin, NULL, 0)) < 0) { + warn("reset"); + code = -1; + lostpeer(0); + } else if (nfnd) + (void)getreply(0); + } +} + +char * +gunique(const char *local) +{ + static char new[MAXPATHLEN]; + char *cp = strrchr(local, '/'); + int d, count=0, len; + char ext = '1'; + + if (cp) + *cp = '\0'; + d = access(cp == local ? "/" : cp ? local : ".", W_OK); + if (cp) + *cp = '/'; + if (d < 0) { + warn("local: %s", local); + return (NULL); + } + len = strlcpy(new, local, sizeof(new)); + cp = &new[len]; + *cp++ = '.'; + while (!d) { + if (++count == 100) { + fputs("runique: can't find unique file name.\n", + ttyout); + return (NULL); + } + *cp++ = ext; + *cp = '\0'; + if (ext == '9') + ext = '0'; + else + ext++; + if ((d = access(new, F_OK)) < 0) + break; + if (ext != '0') + cp--; + else if (*(cp - 2) == '.') + *(cp - 1) = '1'; + else { + *(cp - 2) = *(cp - 2) + 1; + cp--; + } + } + return (new); +} + +/* + * abort_squared -- + * aborts abort_remote(). lostpeer() is called because if the user is + * too impatient to wait or there's another problem then ftp really + * needs to get back to a known state. + */ +void +abort_squared(int dummy) +{ + char msgbuf[100]; + size_t len; + + sigint_raised = 1; + alarmtimer(0); + len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n", + sizeof(msgbuf)); + write(fileno(ttyout), msgbuf, len); + lostpeer(0); + siglongjmp(xferabort, 1); +} + +void +abort_remote(FILE *din) +{ + char buf[BUFSIZ]; + int nfnd; + + if (cout == NULL) { + warnx("Lost control connection for abort."); + if (ptabflg) + code = -1; + lostpeer(0); + return; + } + /* + * send IAC in urgent mode instead of DM because 4.3BSD places oob mark + * after urgent byte rather than before as is protocol now + */ + buf[0] = IAC; + buf[1] = IP; + buf[2] = IAC; + if (send(fileno(cout), buf, 3, MSG_OOB) != 3) + warn("abort"); + fprintf(cout, "%cABOR\r\n", DM); + (void)fflush(cout); + if ((nfnd = empty(cin, din, 10)) <= 0) { + if (nfnd < 0) + warn("abort"); + if (ptabflg) + code = -1; + lostpeer(0); + } + if (din && (nfnd & 2)) { + while (read(fileno(din), buf, BUFSIZ) > 0) + continue; + } + if (getreply(0) == ERROR && code == 552) { + /* 552 needed for nic style abort */ + (void)getreply(0); + } + (void)getreply(0); +} + +void +ai_unmapped(struct addrinfo *ai) +{ +#ifdef INET6 + struct sockaddr_in6 *sin6; + struct sockaddr_in sin; + socklen_t len; + + if (ai->ai_family != AF_INET6) + return; + if (ai->ai_addrlen != sizeof(struct sockaddr_in6) || + sizeof(sin) > ai->ai_addrlen) + return; + sin6 = (struct sockaddr_in6 *)ai->ai_addr; + if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + return; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + len = sizeof(struct sockaddr_in); + memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], + sizeof(sin.sin_addr)); + sin.sin_port = sin6->sin6_port; + + ai->ai_family = AF_INET; +#if HAVE_SOCKADDR_SA_LEN + sin.sin_len = len; +#endif + memcpy(ai->ai_addr, &sin, len); + ai->ai_addrlen = len; +#endif +} diff --git a/contrib/tnftp/src/ftp_var.h b/contrib/tnftp/src/ftp_var.h new file mode 100644 index 0000000..25f13d4 --- /dev/null +++ b/contrib/tnftp/src/ftp_var.h @@ -0,0 +1,337 @@ +/* $NetBSD: ftp_var.h,v 1.71 2005/04/11 01:49:31 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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 + */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FTP global variables. + */ + +#ifdef SMALL +#undef NO_EDITCOMPLETE +#define NO_EDITCOMPLETE +#undef NO_PROGRESS +#define NO_PROGRESS +#endif + +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <poll.h> + +#include <setjmp.h> +#include <stringlist.h> + +#ifndef NO_EDITCOMPLETE +#include <histedit.h> +#endif /* !NO_EDITCOMPLETE */ + +#include "extern.h" +#include "progressbar.h" + +/* + * Format of command table. + */ +struct cmd { + char *c_name; /* name of command */ + const char *c_help; /* help string */ + char c_bell; /* give bell when command completes */ + char c_conn; /* must be connected to use command */ + char c_proxy; /* proxy server may execute */ +#ifndef NO_EDITCOMPLETE + const char *c_complete; /* context sensitive completion list */ +#endif /* !NO_EDITCOMPLETE */ + void (*c_handler)(int, char **); /* function to call */ +}; + +/* + * Format of macro table + */ +struct macel { + char mac_name[9]; /* macro name */ + char *mac_start; /* start of macro in macbuf */ + char *mac_end; /* end of macro in macbuf */ +}; + +/* + * Format of option table + */ +struct option { + char *name; + char *value; +}; + +/* + * Indices to features[]; an array containing status of remote server + * features; -1 not known (FEAT failed), 0 absent, 1 present. + */ +enum { + FEAT_FEAT = 0, /* FEAT, OPTS */ + FEAT_MDTM, /* MDTM */ + FEAT_MLST, /* MLSD, MLST */ + FEAT_REST_STREAM, /* RESTart STREAM */ + FEAT_SIZE, /* SIZE */ + FEAT_TVFS, /* TVFS (not used) */ + FEAT_max +}; + + +/* + * Global defines + */ +#define FTPBUFLEN MAXPATHLEN + 200 +#define MAX_IN_PORT_T 0xffffU + +#define HASHBYTES 1024 /* default mark for `hash' command */ +#define DEFAULTINCR 1024 /* default increment for `rate' command */ + +#define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */ +#define HTTP_PORT 80 /* default if ! getservbyname("http/tcp") */ +#ifndef GATE_PORT +#define GATE_PORT 21 /* default if ! getservbyname("ftpgate/tcp") */ +#endif +#ifndef GATE_SERVER +#define GATE_SERVER "" /* default server */ +#endif + +#define DEFAULTPAGER "more" /* default pager if $PAGER isn't set */ +#define DEFAULTPROMPT "ftp> " /* default prompt if `set prompt' is empty */ +#define DEFAULTRPROMPT "" /* default rprompt if `set rprompt' is empty */ + +#define TMPFILE "ftpXXXXXXXXXX" + + +#ifndef GLOBAL +#define GLOBAL extern +#endif + +/* + * Options and other state info. + */ +GLOBAL int trace; /* trace packets exchanged */ +GLOBAL int hash; /* print # for each buffer transferred */ +GLOBAL int mark; /* number of bytes between hashes */ +GLOBAL int sendport; /* use PORT/LPRT cmd for each data connection */ +GLOBAL int connected; /* 1 = connected to server, -1 = logged in */ +GLOBAL int interactive; /* interactively prompt on m* cmds */ +GLOBAL int confirmrest; /* confirm rest of current m* cmd */ +GLOBAL int debug; /* debugging level */ +GLOBAL int bell; /* ring bell on cmd completion */ +GLOBAL int doglob; /* glob local file names */ +GLOBAL int autologin; /* establish user account on connection */ +GLOBAL int proxy; /* proxy server connection active */ +GLOBAL int proxflag; /* proxy connection exists */ +GLOBAL int gatemode; /* use gate-ftp */ +GLOBAL char *gateserver; /* server to use for gate-ftp */ +GLOBAL int sunique; /* store files on server with unique name */ +GLOBAL int runique; /* store local files with unique name */ +GLOBAL int mcase; /* map upper to lower case for mget names */ +GLOBAL int ntflag; /* use ntin ntout tables for name translation */ +GLOBAL int mapflag; /* use mapin mapout templates on file names */ +GLOBAL int preserve; /* preserve modification time on files */ +GLOBAL int code; /* return/reply code for ftp command */ +GLOBAL int crflag; /* if 1, strip car. rets. on ascii gets */ +GLOBAL int passivemode; /* passive mode enabled */ +GLOBAL int activefallback; /* fall back to active mode if passive fails */ +GLOBAL char *altarg; /* argv[1] with no shell-like preprocessing */ +GLOBAL char ntin[17]; /* input translation table */ +GLOBAL char ntout[17]; /* output translation table */ +GLOBAL char mapin[MAXPATHLEN]; /* input map template */ +GLOBAL char mapout[MAXPATHLEN]; /* output map template */ +GLOBAL char typename[32]; /* name of file transfer type */ +GLOBAL int type; /* requested file transfer type */ +GLOBAL int curtype; /* current file transfer type */ +GLOBAL char structname[32]; /* name of file transfer structure */ +GLOBAL int stru; /* file transfer structure */ +GLOBAL char formname[32]; /* name of file transfer format */ +GLOBAL int form; /* file transfer format */ +GLOBAL char modename[32]; /* name of file transfer mode */ +GLOBAL int mode; /* file transfer mode */ +GLOBAL char bytename[32]; /* local byte size in ascii */ +GLOBAL int bytesize; /* local byte size in binary */ +GLOBAL int anonftp; /* automatic anonymous login */ +GLOBAL int dirchange; /* remote directory changed by cd command */ +GLOBAL int flushcache; /* set HTTP cache flush headers with request */ +GLOBAL int rate_get; /* maximum get xfer rate */ +GLOBAL int rate_get_incr; /* increment for get xfer rate */ +GLOBAL int rate_put; /* maximum put xfer rate */ +GLOBAL int rate_put_incr; /* increment for put xfer rate */ +GLOBAL int retry_connect; /* seconds between retrying connection */ +GLOBAL char *tmpdir; /* temporary directory */ +GLOBAL int epsv4; /* use EPSV/EPRT on IPv4 connections */ +GLOBAL int epsv4bad; /* EPSV doesn't work on the current server */ +GLOBAL int editing; /* command line editing enabled */ +GLOBAL int features[FEAT_max]; /* remote FEATures supported */ + +#ifndef NO_EDITCOMPLETE +GLOBAL EditLine *el; /* editline(3) status structure */ +GLOBAL History *hist; /* editline(3) history structure */ +GLOBAL char *cursor_pos; /* cursor position we're looking for */ +GLOBAL size_t cursor_argc; /* location of cursor in margv */ +GLOBAL size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */ +#endif /* !NO_EDITCOMPLETE */ + +GLOBAL char *direction; /* direction transfer is occurring */ + +GLOBAL char *hostname; /* name of host connected to */ +GLOBAL int unix_server; /* server is unix, can use binary for ascii */ +GLOBAL int unix_proxy; /* proxy is unix, can use binary for ascii */ +GLOBAL char localcwd[MAXPATHLEN]; /* local dir */ +GLOBAL char remotecwd[MAXPATHLEN]; /* remote dir */ +GLOBAL char *username; /* name of user logged in as. (dynamic) */ + +GLOBAL sa_family_t family; /* address family to use for connections */ +GLOBAL char *ftpport; /* port number to use for FTP connections */ +GLOBAL char *httpport; /* port number to use for HTTP connections */ +GLOBAL char *gateport; /* port number to use for gateftp connections */ + +GLOBAL char *outfile; /* filename to output URLs to */ +GLOBAL int restartautofetch; /* restart auto-fetch */ + +GLOBAL char line[FTPBUFLEN]; /* input line buffer */ +GLOBAL char *stringbase; /* current scan point in line buffer */ +GLOBAL char argbuf[FTPBUFLEN]; /* argument storage buffer */ +GLOBAL char *argbase; /* current storage point in arg buffer */ +GLOBAL StringList *marg_sl; /* stringlist containing margv */ +GLOBAL int margc; /* count of arguments on input line */ +#define margv (marg_sl->sl_str) /* args parsed from input line */ +GLOBAL int cpend; /* flag: if != 0, then pending server reply */ +GLOBAL int mflag; /* flag: if != 0, then active multi command */ + +GLOBAL int options; /* used during socket creation */ + +GLOBAL int sndbuf_size; /* socket send buffer size */ +GLOBAL int rcvbuf_size; /* socket receive buffer size */ + +GLOBAL int macnum; /* number of defined macros */ +GLOBAL struct macel macros[16]; +GLOBAL char macbuf[4096]; + +GLOBAL char *localhome; /* local home directory */ +GLOBAL char *localname; /* local user name */ +GLOBAL char netrc[MAXPATHLEN]; /* path to .netrc file */ +GLOBAL char reply_string[BUFSIZ]; /* first line of previous reply */ +GLOBAL void (*reply_callback)(const char *); + /* + * function to call for each line in + * the server's reply except for the + * first (`xxx-') and last (`xxx ') + */ + +GLOBAL volatile sig_atomic_t sigint_raised; + +GLOBAL FILE *cin; +GLOBAL FILE *cout; +GLOBAL int data; + +extern struct cmd cmdtab[]; +extern struct option optiontab[]; + + +#define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0')) +#define FREEPTR(x) if ((x) != NULL) { free(x); (x) = NULL; } + +#ifdef BSD4_4 +# define HAVE_SOCKADDR_SA_LEN 1 +#endif + +#ifdef NO_LONG_LONG +# define STRTOLL(x,y,z) strtol(x,y,z) +#else +# define STRTOLL(x,y,z) strtoll(x,y,z) +#endif diff --git a/contrib/tnftp/src/main.c b/contrib/tnftp/src/main.c new file mode 100644 index 0000000..def05c5 --- /dev/null +++ b/contrib/tnftp/src/main.c @@ -0,0 +1,1052 @@ +/* $NetBSD: main.c,v 1.94 2005/05/13 05:03:49 lukem Exp $ */ + +/*- + * Copyright (c) 1996-2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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. + */ + +/* + * Copyright (C) 1997 and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94"; +#else +__RCSID("$NetBSD: main.c,v 1.94 2005/05/13 05:03:49 lukem Exp $"); +#endif +#endif /* not lint */ + +/* + * FTP User Program -- Command Interface. + */ +#include <sys/types.h> +#include <sys/socket.h> + +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <locale.h> + +#define GLOBAL /* force GLOBAL decls in ftp_var.h to be declared */ +#include "ftp_var.h" + +#define FTP_PROXY "ftp_proxy" /* env var with FTP proxy location */ +#define HTTP_PROXY "http_proxy" /* env var with HTTP proxy location */ +#define NO_PROXY "no_proxy" /* env var with list of non-proxied + * hosts, comma or space separated */ + +static void setupoption(char *, char *, char *); +int main(int, char *[]); + +int +main(int argc, char *argv[]) +{ + int ch, rval; + struct passwd *pw; + char *cp, *ep, *anonuser, *anonpass, *upload_path; + int dumbterm, s, len, isupload; + socklen_t slen; + + setlocale(LC_ALL, ""); + setprogname(argv[0]); + + sigint_raised = 0; + + ftpport = "ftp"; + httpport = "http"; + gateport = NULL; + cp = getenv("FTPSERVERPORT"); + if (cp != NULL) + gateport = cp; + else + gateport = "ftpgate"; + doglob = 1; + interactive = 1; + autologin = 1; + passivemode = 1; + activefallback = 1; + preserve = 1; + verbose = 0; + progress = 0; + gatemode = 0; + data = -1; + outfile = NULL; + restartautofetch = 0; +#ifndef NO_EDITCOMPLETE + editing = 0; + el = NULL; + hist = NULL; +#endif + bytes = 0; + mark = HASHBYTES; + rate_get = 0; + rate_get_incr = DEFAULTINCR; + rate_put = 0; + rate_put_incr = DEFAULTINCR; +#ifdef INET6 + epsv4 = 1; +#else + epsv4 = 0; +#endif + epsv4bad = 0; + upload_path = NULL; + isupload = 0; + reply_callback = NULL; + family = AF_UNSPEC; + + netrc[0] = '\0'; + cp = getenv("NETRC"); + if (cp != NULL && strlcpy(netrc, cp, sizeof(netrc)) >= sizeof(netrc)) + errx(1, "$NETRC `%s': %s", cp, strerror(ENAMETOOLONG)); + + /* + * Get the default socket buffer sizes if we don't already have them. + * It doesn't matter which socket we do this to, because on the first + * call no socket buffer sizes will have been modified, so we are + * guaranteed to get the system defaults. + */ + s = socket(AF_INET, SOCK_STREAM, 0); + if (s == -1) + err(1, "can't create socket"); + slen = sizeof(rcvbuf_size); + if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, + (void *)&rcvbuf_size, &slen) == -1) + err(1, "unable to get default rcvbuf size"); + slen = sizeof(sndbuf_size); + if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, + (void *)&sndbuf_size, &slen) == -1) + err(1, "unable to get default sndbuf size"); + (void)close(s); + /* sanity check returned buffer sizes */ + if (rcvbuf_size <= 0) + rcvbuf_size = 8 * 1024; + if (sndbuf_size <= 0) + sndbuf_size = 8 * 1024; + + if (sndbuf_size > 8 * 1024 * 1024) + sndbuf_size = 8 * 1024 * 1024; + if (rcvbuf_size > 8 * 1024 * 1024) + rcvbuf_size = 8 * 1024 * 1024; + + marg_sl = xsl_init(); + if ((tmpdir = getenv("TMPDIR")) == NULL) + tmpdir = _PATH_TMP; + + /* Set default operation mode based on FTPMODE environment variable */ + if ((cp = getenv("FTPMODE")) != NULL) { + if (strcasecmp(cp, "passive") == 0) { + passivemode = 1; + activefallback = 0; + } else if (strcasecmp(cp, "active") == 0) { + passivemode = 0; + activefallback = 0; + } else if (strcasecmp(cp, "gate") == 0) { + gatemode = 1; + } else if (strcasecmp(cp, "auto") == 0) { + passivemode = 1; + activefallback = 1; + } else + warnx("unknown $FTPMODE '%s'; using defaults", cp); + } + + if (strcmp(getprogname(), "pftp") == 0) { + passivemode = 1; + activefallback = 0; + } else if (strcmp(getprogname(), "gate-ftp") == 0) + gatemode = 1; + + gateserver = getenv("FTPSERVER"); + if (gateserver == NULL || *gateserver == '\0') + gateserver = GATE_SERVER; + if (gatemode) { + if (*gateserver == '\0') { + warnx( +"Neither $FTPSERVER nor GATE_SERVER is defined; disabling gate-ftp"); + gatemode = 0; + } + } + + cp = getenv("TERM"); + if (cp == NULL || strcmp(cp, "dumb") == 0) + dumbterm = 1; + else + dumbterm = 0; + fromatty = isatty(fileno(stdin)); + ttyout = stdout; + if (isatty(fileno(ttyout))) { + verbose = 1; /* verbose if to a tty */ + if (! dumbterm) { +#ifndef NO_EDITCOMPLETE + if (fromatty) /* editing mode on if tty is usable */ + editing = 1; +#endif +#ifndef NO_PROGRESS + if (foregroundproc()) + progress = 1; /* progress bar on if fg */ +#endif + } + } + + while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:RtT:u:vV")) != -1) { + switch (ch) { + case '4': + family = AF_INET; + break; + + case '6': +#ifdef INET6 + family = AF_INET6; +#else + warnx("INET6 support is not available; ignoring -6"); +#endif + break; + + case 'A': + activefallback = 0; + passivemode = 0; + break; + + case 'a': + anonftp = 1; + break; + + case 'd': + options |= SO_DEBUG; + debug++; + break; + + case 'e': +#ifndef NO_EDITCOMPLETE + editing = 0; +#endif + break; + + case 'f': + flushcache = 1; + break; + + case 'g': + doglob = 0; + break; + + case 'i': + interactive = 0; + break; + + case 'n': + autologin = 0; + break; + + case 'N': + if (strlcpy(netrc, optarg, sizeof(netrc)) + >= sizeof(netrc)) + errx(1, "%s: %s", optarg, + strerror(ENAMETOOLONG)); + break; + + case 'o': + outfile = optarg; + if (strcmp(outfile, "-") == 0) + ttyout = stderr; + break; + + case 'p': + passivemode = 1; + activefallback = 0; + break; + + case 'P': + ftpport = optarg; + break; + + case 'q': + quit_time = strtol(optarg, &ep, 10); + if (quit_time < 1 || *ep != '\0') + errx(1, "bad quit value: %s", optarg); + break; + + case 'r': + retry_connect = strtol(optarg, &ep, 10); + if (retry_connect < 1 || *ep != '\0') + errx(1, "bad retry value: %s", optarg); + break; + + case 'R': + restartautofetch = 1; + break; + + case 't': + trace = 1; + break; + + case 'T': + { + int targc; + char *targv[6], *oac; + + /* look for `dir,max[,incr]' */ + targc = 0; + targv[targc++] = "-T"; + oac = xstrdup(optarg); + + while ((cp = strsep(&oac, ",")) != NULL) { + if (*cp == '\0') { + warnx("bad throttle value: %s", optarg); + usage(); + /* NOTREACHED */ + } + targv[targc++] = cp; + if (targc >= 5) + break; + } + if (parserate(targc, targv, 1) == -1) + usage(); + free(oac); + break; + } + + case 'u': + { + isupload = 1; + interactive = 0; + upload_path = xstrdup(optarg); + + break; + } + + case 'v': + progress = verbose = 1; + break; + + case 'V': + progress = verbose = 0; + break; + + default: + usage(); + } + } + /* set line buffering on ttyout */ + setvbuf(ttyout, NULL, _IOLBF, 0); + argc -= optind; + argv += optind; + + cpend = 0; /* no pending replies */ + proxy = 0; /* proxy not active */ + crflag = 1; /* strip c.r. on ascii gets */ + sendport = -1; /* not using ports */ + + /* + * Cache the user name and home directory. + */ + localhome = NULL; + localname = NULL; + anonuser = "anonymous"; + cp = getenv("HOME"); + if (! EMPTYSTRING(cp)) + localhome = xstrdup(cp); + pw = NULL; + cp = getlogin(); + if (cp != NULL) + pw = getpwnam(cp); + if (pw == NULL) + pw = getpwuid(getuid()); + if (pw != NULL) { + if (localhome == NULL && !EMPTYSTRING(pw->pw_dir)) + localhome = xstrdup(pw->pw_dir); + localname = xstrdup(pw->pw_name); + anonuser = localname; + } + if (netrc[0] == '\0' && localhome != NULL) { + if (strlcpy(netrc, localhome, sizeof(netrc)) >= sizeof(netrc) || + strlcat(netrc, "/.netrc", sizeof(netrc)) >= sizeof(netrc)) { + warnx("%s/.netrc: %s", localhome, + strerror(ENAMETOOLONG)); + netrc[0] = '\0'; + } + } + if (localhome == NULL) + localhome = xstrdup("/"); + + /* + * Every anonymous FTP server I've encountered will accept the + * string "username@", and will append the hostname itself. We + * do this by default since many servers are picky about not + * having a FQDN in the anonymous password. + * - thorpej@NetBSD.org + */ + len = strlen(anonuser) + 2; + anonpass = xmalloc(len); + (void)strlcpy(anonpass, anonuser, len); + (void)strlcat(anonpass, "@", len); + + /* + * set all the defaults for options defined in + * struct option optiontab[] declared in cmdtab.c + */ + setupoption("anonpass", getenv("FTPANONPASS"), anonpass); + setupoption("ftp_proxy", getenv(FTP_PROXY), ""); + setupoption("http_proxy", getenv(HTTP_PROXY), ""); + setupoption("no_proxy", getenv(NO_PROXY), ""); + setupoption("pager", getenv("PAGER"), DEFAULTPAGER); + setupoption("prompt", getenv("FTPPROMPT"), DEFAULTPROMPT); + setupoption("rprompt", getenv("FTPRPROMPT"), DEFAULTRPROMPT); + + free(anonpass); + + setttywidth(0); +#ifdef SIGINFO + (void)xsignal(SIGINFO, psummary); +#endif + (void)xsignal(SIGQUIT, psummary); + (void)xsignal(SIGUSR1, crankrate); + (void)xsignal(SIGUSR2, crankrate); + (void)xsignal(SIGWINCH, setttywidth); + +#ifdef __GNUC__ /* to shut up gcc warnings */ + (void)&argc; + (void)&argv; +#endif + + if (argc > 0) { + if (isupload) { + rval = auto_put(argc, argv, upload_path); + sigint_or_rval_exit: + if (sigint_raised) { + (void)xsignal(SIGINT, SIG_DFL); + raise(SIGINT); + } + exit(rval); + } else if (strchr(argv[0], ':') != NULL + && ! isipv6addr(argv[0])) { + rval = auto_fetch(argc, argv); + if (rval >= 0) /* -1 == connected and cd-ed */ + goto sigint_or_rval_exit; + } else { + char *xargv[4], *user, *host; + + if ((rval = sigsetjmp(toplevel, 1))) + goto sigint_or_rval_exit; + (void)xsignal(SIGINT, intr); + (void)xsignal(SIGPIPE, lostpeer); + user = NULL; + host = argv[0]; + cp = strchr(host, '@'); + if (cp) { + *cp = '\0'; + user = host; + host = cp + 1; + } + /* XXX discards const */ + xargv[0] = (char *)getprogname(); + xargv[1] = host; + xargv[2] = argv[1]; + xargv[3] = NULL; + do { + int oautologin; + + oautologin = autologin; + if (user != NULL) { + anonftp = 0; + autologin = 0; + } + setpeer(argc+1, xargv); + autologin = oautologin; + if (connected == 1 && user != NULL) + (void)ftp_login(host, user, NULL); + if (!retry_connect) + break; + if (!connected) { + macnum = 0; + fprintf(ttyout, + "Retrying in %d seconds...\n", + retry_connect); + sleep(retry_connect); + } + } while (!connected); + retry_connect = 0; /* connected, stop hiding msgs */ + } + } + if (isupload) + usage(); + +#ifndef NO_EDITCOMPLETE + controlediting(); +#endif /* !NO_EDITCOMPLETE */ + + (void)sigsetjmp(toplevel, 1); + (void)xsignal(SIGINT, intr); + (void)xsignal(SIGPIPE, lostpeer); + for (;;) + cmdscanner(); +} + +/* + * Generate a prompt + */ +char * +prompt(void) +{ + static char **prompt; + static char buf[MAXPATHLEN]; + + if (prompt == NULL) { + struct option *o; + + o = getoption("prompt"); + if (o == NULL) + errx(1, "no such option `prompt'"); + prompt = &(o->value); + } + formatbuf(buf, sizeof(buf), *prompt ? *prompt : DEFAULTPROMPT); + return (buf); +} + +/* + * Generate an rprompt + */ +char * +rprompt(void) +{ + static char **rprompt; + static char buf[MAXPATHLEN]; + + if (rprompt == NULL) { + struct option *o; + + o = getoption("rprompt"); + if (o == NULL) + errx(1, "no such option `rprompt'"); + rprompt = &(o->value); + } + formatbuf(buf, sizeof(buf), *rprompt ? *rprompt : DEFAULTRPROMPT); + return (buf); +} + +/* + * Command parser. + */ +void +cmdscanner(void) +{ + struct cmd *c; + char *p; + int num; + + for (;;) { +#ifndef NO_EDITCOMPLETE + if (!editing) { +#endif /* !NO_EDITCOMPLETE */ + if (fromatty) { + fputs(prompt(), ttyout); + p = rprompt(); + if (*p) + fprintf(ttyout, "%s ", p); + (void)fflush(ttyout); + } + if (fgets(line, sizeof(line), stdin) == NULL) { + if (fromatty) + putc('\n', ttyout); + quit(0, NULL); + } + num = strlen(line); + if (num == 0) + break; + if (line[--num] == '\n') { + if (num == 0) + break; + line[num] = '\0'; + } else if (num == sizeof(line) - 2) { + fputs("Sorry, input line is too long.\n", + ttyout); + while ((num = getchar()) != '\n' && num != EOF) + /* void */; + break; + } /* else it was a line without a newline */ +#ifndef NO_EDITCOMPLETE + } else { + const char *buf; + HistEvent ev; + cursor_pos = NULL; + + buf = el_gets(el, &num); + if (buf == NULL || num == 0) { + if (fromatty) + putc('\n', ttyout); + quit(0, NULL); + } + if (num >= sizeof(line)) { + fputs("Sorry, input line is too long.\n", + ttyout); + break; + } + memcpy(line, buf, num); + if (line[--num] == '\n') { + line[num] = '\0'; + if (num == 0) + break; + } + history(hist, &ev, H_ENTER, buf); + } +#endif /* !NO_EDITCOMPLETE */ + + makeargv(); + if (margc == 0) + continue; + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + fputs("?Ambiguous command.\n", ttyout); + continue; + } + if (c == NULL) { +#if !defined(NO_EDITCOMPLETE) + /* + * attempt to el_parse() unknown commands. + * any command containing a ':' would be parsed + * as "[prog:]cmd ...", and will result in a + * false positive if prog != "ftp", so treat + * such commands as invalid. + */ + if (strchr(margv[0], ':') != NULL || + !editing || + el_parse(el, margc, (const char **)margv) != 0) +#endif /* !NO_EDITCOMPLETE */ + fputs("?Invalid command.\n", ttyout); + continue; + } + if (c->c_conn && !connected) { + fputs("Not connected.\n", ttyout); + continue; + } + confirmrest = 0; + margv[0] = c->c_name; + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) + (void)putc('\007', ttyout); + if (c->c_handler != help) + break; + } + (void)xsignal(SIGINT, intr); + (void)xsignal(SIGPIPE, lostpeer); +} + +struct cmd * +getcmd(const char *name) +{ + const char *p, *q; + struct cmd *c, *found; + int nmatches, longest; + + if (name == NULL) + return (0); + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; (p = c->c_name) != NULL; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return (c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return ((struct cmd *)-1); + return (found); +} + +/* + * Slice a string up into argc/argv. + */ + +int slrflag; + +void +makeargv(void) +{ + char *argp; + + stringbase = line; /* scan from first of buffer */ + argbase = argbuf; /* store from first of buffer */ + slrflag = 0; + marg_sl->sl_cur = 0; /* reset to start of marg_sl */ + for (margc = 0; ; margc++) { + argp = slurpstring(); + xsl_add(marg_sl, argp); + if (argp == NULL) + break; + } +#ifndef NO_EDITCOMPLETE + if (cursor_pos == line) { + cursor_argc = 0; + cursor_argo = 0; + } else if (cursor_pos != NULL) { + cursor_argc = margc; + cursor_argo = strlen(margv[margc-1]); + } +#endif /* !NO_EDITCOMPLETE */ +} + +#ifdef NO_EDITCOMPLETE +#define INC_CHKCURSOR(x) (x)++ +#else /* !NO_EDITCOMPLETE */ +#define INC_CHKCURSOR(x) { (x)++ ; \ + if (x == cursor_pos) { \ + cursor_argc = margc; \ + cursor_argo = ap-argbase; \ + cursor_pos = NULL; \ + } } + +#endif /* !NO_EDITCOMPLETE */ + +/* + * 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++; + INC_CHKCURSOR(stringbase); + return ((*sb == '!') ? "!" : "$"); + /* NOTREACHED */ + case 1: + slrflag++; + altarg = stringbase; + break; + default: + break; + } + } + +S0: + switch (*sb) { + + case '\0': + goto OUT; + + case ' ': + case '\t': + INC_CHKCURSOR(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 '\\': + INC_CHKCURSOR(sb); + goto S2; /* slurp next character */ + + case '"': + INC_CHKCURSOR(sb); + goto S3; /* slurp quoted string */ + + default: + *ap = *sb; /* add character to token */ + ap++; + INC_CHKCURSOR(sb); + got_one = 1; + goto S1; + } + +S2: + switch (*sb) { + + case '\0': + goto OUT; + + default: + *ap = *sb; + ap++; + INC_CHKCURSOR(sb); + got_one = 1; + goto S1; + } + +S3: + switch (*sb) { + + case '\0': + goto OUT; + + case '"': + INC_CHKCURSOR(sb); + goto S1; + + default: + *ap = *sb; + ap++; + INC_CHKCURSOR(sb); + got_one = 1; + goto S3; + } + +OUT: + if (got_one) + *ap++ = '\0'; + argbase = ap; /* update storage pointer */ + stringbase = sb; /* update scan pointer */ + if (got_one) { + return (tmp); + } + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = NULL; + break; + default: + break; + } + return (NULL); +} + +/* + * Help/usage command. + * Call each command handler with argc == 0 and argv[0] == name. + */ +void +help(int argc, char *argv[]) +{ + struct cmd *c; + char *nargv[1], *p, *cmd; + int isusage; + + cmd = argv[0]; + isusage = (strcmp(cmd, "usage") == 0); + if (argc == 0 || (isusage && argc == 1)) { + fprintf(ttyout, "usage: %s [command [...]]\n", cmd); + return; + } + if (argc == 1) { + StringList *buf; + + buf = xsl_init(); + fprintf(ttyout, + "%sommands may be abbreviated. Commands are:\n\n", + proxy ? "Proxy c" : "C"); + for (c = cmdtab; (p = c->c_name) != NULL; c++) + if (!proxy || c->c_proxy) + xsl_add(buf, p); + list_vertical(buf); + sl_free(buf, 0); + return; + } + +#define HELPINDENT ((int) sizeof("disconnect")) + + while (--argc > 0) { + char *arg; + + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + fprintf(ttyout, "?Ambiguous %s command `%s'\n", + cmd, arg); + else if (c == NULL) + fprintf(ttyout, "?Invalid %s command `%s'\n", + cmd, arg); + else { + if (isusage) { + nargv[0] = c->c_name; + (*c->c_handler)(0, nargv); + } else + fprintf(ttyout, "%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } + } +} + +struct option * +getoption(const char *name) +{ + const char *p; + struct option *c; + + if (name == NULL) + return (NULL); + for (c = optiontab; (p = c->name) != NULL; c++) { + if (strcasecmp(p, name) == 0) + return (c); + } + return (NULL); +} + +char * +getoptionvalue(const char *name) +{ + struct option *c; + + if (name == NULL) + errx(1, "getoptionvalue() invoked with NULL name"); + c = getoption(name); + if (c != NULL) + return (c->value); + errx(1, "getoptionvalue() invoked with unknown option `%s'", name); + /* NOTREACHED */ +} + +static void +setupoption(char *name, char *value, char *defaultvalue) +{ + char *nargv[3]; + int overbose; + + nargv[0] = "setupoption()"; + nargv[1] = name; + nargv[2] = (value ? value : defaultvalue); + overbose = verbose; + verbose = 0; + setoption(3, nargv); + verbose = overbose; +} + +void +usage(void) +{ + const char *progname = getprogname(); + + (void)fprintf(stderr, +"usage: %s [-46AadefginpRtvV] [-N netrc] [-o outfile] [-P port] [-q quittime]\n" +" [-r retry] [-T dir,max[,inc][[user@]host [port]]] [host:path[/]]\n" +" [file:///file] [ftp://[user[:pass]@]host[:port]/path[/]]\n" +" [http://[user[:pass]@]host[:port]/path] [...]\n" +" %s -u URL file [...]\n", progname, progname); + exit(1); +} diff --git a/contrib/tnftp/src/progressbar.c b/contrib/tnftp/src/progressbar.c new file mode 100644 index 0000000..d0bd35f --- /dev/null +++ b/contrib/tnftp/src/progressbar.c @@ -0,0 +1,464 @@ +/* $NetBSD: progressbar.c,v 1.7 2005/04/11 01:49:31 lukem Exp $ */ + +/*- + * Copyright (c) 1997-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: progressbar.c,v 1.7 2005/04/11 01:49:31 lukem Exp $"); +#endif /* not lint */ + +/* + * FTP User Program -- Misc support routines + */ +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> + +#include <err.h> +#include <errno.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "progressbar.h" + +#define SECSPERHOUR (60 * 60) +#define SECSPERDAY ((long)60 * 60 * 24) + +#if !defined(NO_PROGRESS) +/* + * return non-zero if we're the current foreground process + */ +int +foregroundproc(void) +{ + static pid_t pgrp = -1; + + if (pgrp == -1) + pgrp = getpgrp(); + + return (tcgetpgrp(fileno(ttyout)) == pgrp); +} +#endif /* !defined(NO_PROGRESS) */ + + +static void updateprogressmeter(int); + +/* + * SIGALRM handler to update the progress meter + */ +static void +updateprogressmeter(int dummy) +{ + int oerrno = errno; + + progressmeter(0); + errno = oerrno; +} + +/* + * List of order of magnitude prefixes. + * The last is `P', as 2^64 = 16384 Petabytes + */ +static const char prefixes[] = " KMGTP"; + +/* + * Display a transfer progress bar if progress is non-zero. + * SIGALRM is hijacked for use by this function. + * - Before the transfer, set filesize to size of file (or -1 if unknown), + * and call with flag = -1. This starts the once per second timer, + * and a call to updateprogressmeter() upon SIGALRM. + * - During the transfer, updateprogressmeter will call progressmeter + * with flag = 0 + * - After the transfer, call with flag = 1 + */ +static struct timeval start; +static struct timeval lastupdate; + +#define BUFLEFT (sizeof(buf) - len) + +void +progressmeter(int flag) +{ + static off_t lastsize; + off_t cursize; + struct timeval now, wait; +#ifndef NO_PROGRESS + struct timeval td; + off_t abbrevsize, bytespersec; + double elapsed; + int ratio, barlength, i, remaining; + + /* + * Work variables for progress bar. + * + * XXX: if the format of the progress bar changes + * (especially the number of characters in the + * `static' portion of it), be sure to update + * these appropriately. + */ +#endif + int len; + char buf[256]; /* workspace for progress bar */ +#ifndef NO_PROGRESS +#define BAROVERHEAD 43 /* non `*' portion of progress bar */ + /* + * stars should contain at least + * sizeof(buf) - BAROVERHEAD entries + */ + static const char stars[] = +"*****************************************************************************" +"*****************************************************************************" +"*****************************************************************************"; + +#endif + + if (flag == -1) { + (void)gettimeofday(&start, NULL); + lastupdate = start; + lastsize = restart_point; + } + + (void)gettimeofday(&now, NULL); + cursize = bytes + restart_point; + timersub(&now, &lastupdate, &wait); + if (cursize > lastsize) { + lastupdate = now; + lastsize = cursize; + wait.tv_sec = 0; + } else { +#ifndef STANDALONE_PROGRESS + if (quit_time > 0 && wait.tv_sec > quit_time) { + len = snprintf(buf, sizeof(buf), "\r\n%s: " + "transfer aborted because stalled for %lu sec.\r\n", + getprogname(), (unsigned long)wait.tv_sec); + (void)write(fileno(ttyout), buf, len); + (void)xsignal(SIGALRM, SIG_DFL); + alarmtimer(0); + siglongjmp(toplevel, 1); + } +#endif /* !STANDALONE_PROGRESS */ + } + /* + * Always set the handler even if we are not the foreground process. + */ +#ifdef STANDALONE_PROGRESS + if (progress) { +#else + if (quit_time > 0 || progress) { +#endif /* !STANDALONE_PROGRESS */ + if (flag == -1) { + (void)xsignal_restart(SIGALRM, updateprogressmeter, 1); + alarmtimer(1); /* set alarm timer for 1 Hz */ + } else if (flag == 1) { + (void)xsignal(SIGALRM, SIG_DFL); + alarmtimer(0); + } + } +#ifndef NO_PROGRESS + if (!progress) + return; + len = 0; + + /* + * print progress bar only if we are foreground process. + */ + if (! foregroundproc()) + return; + + len += snprintf(buf + len, BUFLEFT, "\r"); + if (prefix) + len += snprintf(buf + len, BUFLEFT, "%s", prefix); + if (filesize > 0) { + ratio = (int)((double)cursize * 100.0 / (double)filesize); + ratio = MAX(ratio, 0); + ratio = MIN(ratio, 100); + len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio); + + /* + * calculate the length of the `*' bar, ensuring that + * the number of stars won't exceed the buffer size + */ + barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD; + if (prefix) + barlength -= strlen(prefix); + if (barlength > 0) { + i = barlength * ratio / 100; + len += snprintf(buf + len, BUFLEFT, + "|%.*s%*s|", i, stars, barlength - i, ""); + } + } + + abbrevsize = cursize; + for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++) + abbrevsize >>= 10; + len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ", + (LLT)abbrevsize, + prefixes[i], + i == 0 ? ' ' : 'B'); + + timersub(&now, &start, &td); + elapsed = td.tv_sec + (td.tv_usec / 1000000.0); + + bytespersec = 0; + if (bytes > 0) { + bytespersec = bytes; + if (elapsed > 0.0) + bytespersec /= elapsed; + } + for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) + bytespersec >>= 10; + len += snprintf(buf + len, BUFLEFT, + " " LLFP("3") ".%02d %cB/s ", + (LLT)(bytespersec / 1024), + (int)((bytespersec % 1024) * 100 / 1024), + prefixes[i]); + + if (filesize > 0) { + if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) { + len += snprintf(buf + len, BUFLEFT, " --:-- ETA"); + } else if (wait.tv_sec >= STALLTIME) { + len += snprintf(buf + len, BUFLEFT, " - stalled -"); + } else { + remaining = (int) + ((filesize - restart_point) / (bytes / elapsed) - + elapsed); + if (remaining >= 100 * SECSPERHOUR) + len += snprintf(buf + len, BUFLEFT, + " --:-- ETA"); + else { + i = remaining / SECSPERHOUR; + if (i) + len += snprintf(buf + len, BUFLEFT, + "%2d:", i); + else + len += snprintf(buf + len, BUFLEFT, + " "); + i = remaining % SECSPERHOUR; + len += snprintf(buf + len, BUFLEFT, + "%02d:%02d ETA", i / 60, i % 60); + } + } + } + if (flag == 1) + len += snprintf(buf + len, BUFLEFT, "\n"); + (void)write(fileno(ttyout), buf, len); + +#endif /* !NO_PROGRESS */ +} + +#ifndef STANDALONE_PROGRESS +/* + * Display transfer statistics. + * Requires start to be initialised by progressmeter(-1), + * direction to be defined by xfer routines, and filesize and bytes + * to be updated by xfer routines + * If siginfo is nonzero, an ETA is displayed, and the output goes to stderr + * instead of ttyout. + */ +void +ptransfer(int siginfo) +{ + struct timeval now, td, wait; + double elapsed; + off_t bytespersec; + int remaining, hh, i, len; + + char buf[256]; /* Work variable for transfer status. */ + + if (!verbose && !progress && !siginfo) + return; + + (void)gettimeofday(&now, NULL); + timersub(&now, &start, &td); + elapsed = td.tv_sec + (td.tv_usec / 1000000.0); + bytespersec = 0; + if (bytes > 0) { + bytespersec = bytes; + if (elapsed > 0.0) + bytespersec /= elapsed; + } + len = 0; + len += snprintf(buf + len, BUFLEFT, LLF " byte%s %s in ", + (LLT)bytes, bytes == 1 ? "" : "s", direction); + remaining = (int)elapsed; + if (remaining > SECSPERDAY) { + int days; + + days = remaining / SECSPERDAY; + remaining %= SECSPERDAY; + len += snprintf(buf + len, BUFLEFT, + "%d day%s ", days, days == 1 ? "" : "s"); + } + hh = remaining / SECSPERHOUR; + remaining %= SECSPERHOUR; + if (hh) + len += snprintf(buf + len, BUFLEFT, "%2d:", hh); + len += snprintf(buf + len, BUFLEFT, + "%02d:%02d ", remaining / 60, remaining % 60); + + for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++) + bytespersec >>= 10; + len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)", + (LLT)(bytespersec / 1024), + (int)((bytespersec % 1024) * 100 / 1024), + prefixes[i]); + + if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0 + && bytes + restart_point <= filesize) { + remaining = (int)((filesize - restart_point) / + (bytes / elapsed) - elapsed); + hh = remaining / SECSPERHOUR; + remaining %= SECSPERHOUR; + len += snprintf(buf + len, BUFLEFT, " ETA: "); + if (hh) + len += snprintf(buf + len, BUFLEFT, "%2d:", hh); + len += snprintf(buf + len, BUFLEFT, "%02d:%02d", + remaining / 60, remaining % 60); + timersub(&now, &lastupdate, &wait); + if (wait.tv_sec >= STALLTIME) + len += snprintf(buf + len, BUFLEFT, " (stalled)"); + } + len += snprintf(buf + len, BUFLEFT, "\n"); + (void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len); +} + +/* + * SIG{INFO,QUIT} handler to print transfer stats if a transfer is in progress + */ +void +psummary(int notused) +{ + int oerrno = errno; + + if (bytes > 0) { + if (fromatty) + write(fileno(ttyout), "\n", 1); + ptransfer(1); + } + errno = oerrno; +} +#endif /* !STANDALONE_PROGRESS */ + + +/* + * Set the SIGALRM interval timer for wait seconds, 0 to disable. + */ +void +alarmtimer(int wait) +{ + struct itimerval itv; + + itv.it_value.tv_sec = wait; + itv.it_value.tv_usec = 0; + itv.it_interval = itv.it_value; + setitimer(ITIMER_REAL, &itv, NULL); +} + + +/* + * Install a POSIX signal handler, allowing the invoker to set whether + * the signal should be restartable or not + */ +sigfunc +xsignal_restart(int sig, sigfunc func, int restartable) +{ + struct sigaction act, oact; + act.sa_handler = func; + + sigemptyset(&act.sa_mask); +#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */ + act.sa_flags = restartable ? SA_RESTART : 0; +#elif defined(SA_INTERRUPT) /* SunOS 4.x */ + act.sa_flags = restartable ? 0 : SA_INTERRUPT; +#else +#error "system must have SA_RESTART or SA_INTERRUPT" +#endif + if (sigaction(sig, &act, &oact) < 0) + return (SIG_ERR); + return (oact.sa_handler); +} + +/* + * Install a signal handler with the `restartable' flag set dependent upon + * which signal is being set. (This is a wrapper to xsignal_restart()) + */ +sigfunc +xsignal(int sig, sigfunc func) +{ + int restartable; + + /* + * Some signals print output or change the state of the process. + * There should be restartable, so that reads and writes are + * not affected. Some signals should cause program flow to change; + * these signals should not be restartable, so that the system call + * will return with EINTR, and the program will go do something + * different. If the signal handler calls longjmp() or siglongjmp(), + * it doesn't matter if it's restartable. + */ + + switch(sig) { +#ifdef SIGINFO + case SIGINFO: +#endif + case SIGQUIT: + case SIGUSR1: + case SIGUSR2: + case SIGWINCH: + restartable = 1; + break; + + case SIGALRM: + case SIGINT: + case SIGPIPE: + restartable = 0; + break; + + default: + /* + * This is unpleasant, but I don't know what would be better. + * Right now, this "can't happen" + */ + errx(1, "xsignal_restart called with signal %d", sig); + } + + return(xsignal_restart(sig, func, restartable)); +} diff --git a/contrib/tnftp/src/progressbar.h b/contrib/tnftp/src/progressbar.h new file mode 100644 index 0000000..9e004f4 --- /dev/null +++ b/contrib/tnftp/src/progressbar.h @@ -0,0 +1,99 @@ +/* $NetBSD: progressbar.h,v 1.5 2005/02/10 16:00:38 jmc Exp $ */ + +/*- + * Copyright (c) 1996-2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef STANDALONE_PROGRESS +#include <setjmp.h> +#endif /* !STANDALONE_PROGRESS */ + +#ifndef GLOBAL +#define GLOBAL extern +#endif + + +#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */ + +typedef void (*sigfunc)(int); + + +GLOBAL FILE *ttyout; /* stdout, or stderr if retrieving to stdout */ + +GLOBAL int progress; /* display transfer progress bar */ +GLOBAL int ttywidth; /* width of tty */ + +GLOBAL off_t bytes; /* current # of bytes read */ +GLOBAL off_t filesize; /* size of file being transferred */ +GLOBAL off_t restart_point; /* offset to restart transfer */ +GLOBAL char *prefix; /* Text written left of progress bar */ + + +#ifndef STANDALONE_PROGRESS +GLOBAL int fromatty; /* input is from a terminal */ +GLOBAL int verbose; /* print messages coming back from server */ +GLOBAL int quit_time; /* maximum time to wait if stalled */ + +GLOBAL char *direction; /* direction transfer is occurring */ + +GLOBAL sigjmp_buf toplevel; /* non-local goto stuff for cmd scanner */ +#endif /* !STANDALONE_PROGRESS */ + +int foregroundproc(void); +void alarmtimer(int); +void progressmeter(int); +sigfunc xsignal(int, sigfunc); +sigfunc xsignal_restart(int, sigfunc, int); + +#ifndef STANDALONE_PROGRESS +void psummary(int); +void ptransfer(int); +#endif /* !STANDALONE_PROGRESS */ + +#ifdef NO_LONG_LONG +# define LLF "%ld" +# define LLFP(x) "%" x "ld" +# define LLT long +# define ULLF "%lu" +# define ULLFP(x) "%" x "lu" +# define ULLT unsigned long +#else +# define LLF "%lld" +# define LLFP(x) "%" x "lld" +# define LLT long long +# define ULLF "%llu" +# define ULLFP(x) "%" x "llu" +# define ULLT unsigned long long +#endif diff --git a/contrib/tnftp/src/ruserpass.c b/contrib/tnftp/src/ruserpass.c new file mode 100644 index 0000000..9cb318a --- /dev/null +++ b/contrib/tnftp/src/ruserpass.c @@ -0,0 +1,293 @@ +/* $NetBSD: ruserpass.c,v 1.29 2003/08/07 11:13:57 agc Exp $ */ + +/* + * 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. 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 <sys/cdefs.h> +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; +#else +__RCSID("$NetBSD: ruserpass.c,v 1.29 2003/08/07 11:13:57 agc Exp $"); +#endif +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "ftp_var.h" + +static int token(void); +static FILE *cfile; + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#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 }, + { NULL, 0 } +}; + +int +ruserpass(const char *host, const char **aname, const char **apass, + const char **aacct) +{ + char *tmp; + char myname[MAXHOSTNAMELEN + 1], *mydomain; + int t, i, c, usedefault = 0; + struct stat stb; + + if (netrc[0] == '\0') + return (0); + cfile = fopen(netrc, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + warn("%s", netrc); + return (0); + } + if (gethostname(myname, sizeof(myname)) < 0) + myname[0] = '\0'; + myname[sizeof(myname) - 1] = '\0'; + if ((mydomain = strchr(myname, '.')) == NULL) + mydomain = ""; + next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if (strcasecmp(hostname, tokval) == 0) + goto match; + if ((tmp = strchr(hostname, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(hostname, tokval, tmp-hostname) == 0 && + tokval[tmp - hostname] == '\0') + goto match; + if ((tmp = strchr(host, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) { + if (*aname == NULL) + *aname = xstrdup(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 == NULL) + *apass = xstrdup(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 == NULL) + *aacct = xstrdup(tokval); + break; + case MACDEF: + if (proxy) { + (void)fclose(cfile); + return (0); + } + while ((c = getc(cfile)) != EOF) + if (c != ' ' && c != '\t') + break; + if (c == EOF || c == '\n') { + fputs("Missing macdef name argument.\n", + ttyout); + goto bad; + } + if (macnum == 16) { + fputs( + "Limit of 16 macros have already been defined.\n", + ttyout); + 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) { + fputs( + "Macro definition missing null line terminator.\n", + ttyout); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c = getc(cfile)) != EOF && c != '\n'); + } + if (c == EOF) { + fputs( + "Macro definition missing null line terminator.\n", + ttyout); + 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) { + fputs( + "Macro definition missing null line terminator.\n", + ttyout); + 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) { + fputs("4K macro buffer exceeded.\n", + ttyout); + goto bad; + } + break; + default: + warnx("Unknown .netrc keyword %s", tokval); + break; + } + goto done; + } + done: + (void)fclose(cfile); + return (0); + bad: + (void)fclose(cfile); + return (-1); +} + +static int +token(void) +{ + char *cp; + int c; + struct toktab *t; + + 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/contrib/tnftp/src/util.c b/contrib/tnftp/src/util.c new file mode 100644 index 0000000..6f94bb0 --- /dev/null +++ b/contrib/tnftp/src/util.c @@ -0,0 +1,1400 @@ +/* $NetBSD: util.c,v 1.123 2005/05/14 18:56:45 dsl Exp $ */ + +/*- + * Copyright (c) 1997-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1985, 1989, 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. 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 <sys/cdefs.h> +#ifndef lint +__RCSID("$NetBSD: util.c,v 1.123 2005/05/14 18:56:45 dsl Exp $"); +#endif /* not lint */ + +/* + * FTP User Program -- Misc support routines + */ +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <arpa/ftp.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <glob.h> +#include <signal.h> +#include <limits.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <termios.h> +#include <time.h> +#include <unistd.h> + +#include "ftp_var.h" + +#define TM_YEAR_BASE 1900 + +/* + * Connect to peer server and auto-login, if possible. + */ +void +setpeer(int argc, char *argv[]) +{ + char *host; + char *port; + + if (argc == 0) + goto usage; + if (connected) { + fprintf(ttyout, "Already connected to %s, use close first.\n", + hostname); + code = -1; + return; + } + if (argc < 2) + (void)another(&argc, &argv, "to"); + if (argc < 2 || argc > 3) { + usage: + fprintf(ttyout, "usage: %s host-name [port]\n", argv[0]); + code = -1; + return; + } + if (gatemode) + port = gateport; + else + port = ftpport; + if (argc > 2) + port = argv[2]; + + if (gatemode) { + if (gateserver == NULL || *gateserver == '\0') + errx(1, "gateserver not defined (shouldn't happen)"); + host = hookup(gateserver, port); + } else + host = hookup(argv[1], port); + + if (host) { + if (gatemode && verbose) { + fprintf(ttyout, + "Connecting via pass-through server %s\n", + gateserver); + } + + connected = 1; + /* + * Set up defaults for FTP. + */ + (void)strlcpy(typename, "ascii", sizeof(typename)); + type = TYPE_A; + curtype = TYPE_A; + (void)strlcpy(formname, "non-print", sizeof(formname)); + form = FORM_N; + (void)strlcpy(modename, "stream", sizeof(modename)); + mode = MODE_S; + (void)strlcpy(structname, "file", sizeof(structname)); + stru = STRU_F; + (void)strlcpy(bytename, "8", sizeof(bytename)); + bytesize = 8; + if (autologin) + (void)ftp_login(argv[1], NULL, NULL); + } +} + +static void +parse_feat(const char *line) +{ + + /* + * work-around broken ProFTPd servers that can't + * even obey RFC 2389. + */ + while (*line && isspace((int)*line)) + line++; + + if (strcasecmp(line, "MDTM") == 0) + features[FEAT_MDTM] = 1; + else if (strncasecmp(line, "MLST", sizeof("MLST") - 1) == 0) { + features[FEAT_MLST] = 1; + } else if (strcasecmp(line, "REST STREAM") == 0) + features[FEAT_REST_STREAM] = 1; + else if (strcasecmp(line, "SIZE") == 0) + features[FEAT_SIZE] = 1; + else if (strcasecmp(line, "TVFS") == 0) + features[FEAT_TVFS] = 1; +} + +/* + * Determine the remote system type (SYST) and features (FEAT). + * Call after a successful login (i.e, connected = -1) + */ +void +getremoteinfo(void) +{ + int overbose, i; + + overbose = verbose; + if (debug == 0) + verbose = -1; + + /* determine remote system type */ + if (command("SYST") == COMPLETE) { + if (overbose) { + char *cp, c; + + c = 0; + cp = strchr(reply_string + 4, ' '); + if (cp == NULL) + cp = strchr(reply_string + 4, '\r'); + if (cp) { + if (cp[-1] == '.') + cp--; + c = *cp; + *cp = '\0'; + } + + fprintf(ttyout, "Remote system type is %s.\n", + reply_string + 4); + if (cp) + *cp = c; + } + if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { + if (proxy) + unix_proxy = 1; + else + unix_server = 1; + /* + * Set type to 0 (not specified by user), + * meaning binary by default, but don't bother + * telling server. We can use binary + * for text files unless changed by the user. + */ + type = 0; + (void)strlcpy(typename, "binary", sizeof(typename)); + if (overbose) + fprintf(ttyout, + "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)) + fputs( +"Remember to set tenex mode when transferring binary files from this machine.\n", + ttyout); + } + } + + /* determine features (if any) */ + for (i = 0; i < FEAT_max; i++) + features[i] = -1; + reply_callback = parse_feat; + if (command("FEAT") == COMPLETE) { + for (i = 0; i < FEAT_max; i++) { + if (features[i] == -1) + features[i] = 0; + } + features[FEAT_FEAT] = 1; + } else + features[FEAT_FEAT] = 0; + if (debug) { +#define DEBUG_FEAT(x) fprintf(ttyout, "features[" #x "] = %d\n", features[(x)]) + DEBUG_FEAT(FEAT_FEAT); + DEBUG_FEAT(FEAT_MDTM); + DEBUG_FEAT(FEAT_MLST); + DEBUG_FEAT(FEAT_REST_STREAM); + DEBUG_FEAT(FEAT_SIZE); + DEBUG_FEAT(FEAT_TVFS); +#undef DEBUG_FEAT + } + reply_callback = NULL; + + verbose = overbose; +} + +/* + * Reset the various variables that indicate connection state back to + * disconnected settings. + * The caller is responsible for issuing any commands to the remote server + * to perform a clean shutdown before this is invoked. + */ +void +cleanuppeer(void) +{ + + if (cout) + (void)fclose(cout); + cout = NULL; + connected = 0; + unix_server = 0; + unix_proxy = 0; + /* + * determine if anonftp was specifically set with -a + * (1), or implicitly set by auto_fetch() (2). in the + * latter case, disable after the current xfer + */ + if (anonftp == 2) + anonftp = 0; + data = -1; + epsv4bad = 0; + if (username) + free(username); + username = NULL; + if (!proxy) + macnum = 0; +} + +/* + * Top-level signal handler for interrupted commands. + */ +void +intr(int signo) +{ + + sigint_raised = 1; + alarmtimer(0); + if (fromatty) + write(fileno(ttyout), "\n", 1); + siglongjmp(toplevel, 1); +} + +/* + * Signal handler for lost connections; cleanup various elements of + * the connection state, and call cleanuppeer() to finish it off. + */ +void +lostpeer(int dummy) +{ + int oerrno = errno; + + alarmtimer(0); + if (connected) { + if (cout != NULL) { + (void)shutdown(fileno(cout), 1+1); + (void)fclose(cout); + cout = NULL; + } + if (data >= 0) { + (void)shutdown(data, 1+1); + (void)close(data); + data = -1; + } + connected = 0; + } + pswitch(1); + if (connected) { + if (cout != NULL) { + (void)shutdown(fileno(cout), 1+1); + (void)fclose(cout); + cout = NULL; + } + connected = 0; + } + proxflag = 0; + pswitch(0); + cleanuppeer(); + errno = oerrno; +} + + +/* + * Login to remote host, using given username & password if supplied. + * Return non-zero if successful. + */ +int +ftp_login(const char *host, const char *user, const char *pass) +{ + char tmp[80]; + const char *acct; + int n, aflag, rval, freeuser, freepass, freeacct; + + acct = NULL; + aflag = rval = freeuser = freepass = freeacct = 0; + + if (debug) + fprintf(ttyout, "ftp_login: user `%s' pass `%s' host `%s'\n", + user ? user : "<null>", pass ? pass : "<null>", + host ? host : "<null>"); + + + /* + * Set up arguments for an anonymous FTP session, if necessary. + */ + if (anonftp) { + user = "anonymous"; /* as per RFC 1635 */ + pass = getoptionvalue("anonpass"); + } + + if (user == NULL) + freeuser = 1; + if (pass == NULL) + freepass = 1; + freeacct = 1; + if (ruserpass(host, &user, &pass, &acct) < 0) { + code = -1; + goto cleanup_ftp_login; + } + + while (user == NULL) { + if (localname) + fprintf(ttyout, "Name (%s:%s): ", host, localname); + else + fprintf(ttyout, "Name (%s): ", host); + *tmp = '\0'; + if (fgets(tmp, sizeof(tmp) - 1, stdin) == NULL) { + fprintf(ttyout, "\nEOF received; login aborted.\n"); + clearerr(stdin); + code = -1; + goto cleanup_ftp_login; + } + tmp[strlen(tmp) - 1] = '\0'; + freeuser = 0; + if (*tmp == '\0') + user = localname; + else + user = tmp; + } + + if (gatemode) { + char *nuser; + int len; + + len = strlen(user) + 1 + strlen(host) + 1; + nuser = xmalloc(len); + (void)strlcpy(nuser, user, len); + (void)strlcat(nuser, "@", len); + (void)strlcat(nuser, host, len); + freeuser = 1; + user = nuser; + } + + n = command("USER %s", user); + if (n == CONTINUE) { + if (pass == NULL) { + freepass = 0; + pass = getpass("Password:"); + } + n = command("PASS %s", pass); + } + if (n == CONTINUE) { + aflag++; + if (acct == NULL) { + freeacct = 0; + acct = getpass("Account:"); + } + if (acct[0] == '\0') { + warnx("Login failed."); + goto cleanup_ftp_login; + } + n = command("ACCT %s", acct); + } + if ((n != COMPLETE) || + (!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) { + warnx("Login failed."); + goto cleanup_ftp_login; + } + rval = 1; + username = xstrdup(user); + if (proxy) + goto cleanup_ftp_login; + + connected = -1; + getremoteinfo(); + for (n = 0; n < macnum; ++n) { + if (!strcmp("init", macros[n].mac_name)) { + (void)strlcpy(line, "$init", sizeof(line)); + makeargv(); + domacro(margc, margv); + break; + } + } + updatelocalcwd(); + updateremotecwd(); + + cleanup_ftp_login: + if (user != NULL && freeuser) + free((char *)user); + if (pass != NULL && freepass) + free((char *)pass); + if (acct != NULL && freeacct) + free((char *)acct); + return (rval); +} + +/* + * `another' gets another argument, and stores the new argc and argv. + * It reverts to the top level (via intr()) on EOF/error. + * + * Returns false if no new arguments have been added. + */ +int +another(int *pargc, char ***pargv, const char *prompt) +{ + int len = strlen(line), ret; + + if (len >= sizeof(line) - 3) { + fputs("sorry, arguments too long.\n", ttyout); + intr(0); + } + fprintf(ttyout, "(%s) ", prompt); + line[len++] = ' '; + if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) { + clearerr(stdin); + 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); +} + +/* + * glob files given in argv[] from the remote server. + * if errbuf isn't NULL, store error messages there instead + * of writing to the screen. + */ +char * +remglob(char *argv[], int doswitch, char **errbuf) +{ + char temp[MAXPATHLEN]; + static char buf[MAXPATHLEN]; + static FILE *ftemp = NULL; + static char **args; + int oldverbose, oldhash, oldprogress, fd, len; + char *cp, *mode; + + if (!mflag || !connected) { + if (!doglob) + args = NULL; + else { + if (ftemp) { + (void)fclose(ftemp); + ftemp = NULL; + } + } + return (NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + len = strlcpy(temp, tmpdir, sizeof(temp)); + if (temp[len - 1] != '/') + (void)strlcat(temp, "/", sizeof(temp)); + (void)strlcat(temp, TMPFILE, sizeof(temp)); + if ((fd = mkstemp(temp)) < 0) { + warn("unable to create temporary file %s", temp); + return (NULL); + } + close(fd); + oldverbose = verbose; + verbose = (errbuf != NULL) ? -1 : 0; + oldhash = hash; + oldprogress = progress; + hash = 0; + progress = 0; + if (doswitch) + pswitch(!proxy); + for (mode = "w"; *++argv != NULL; mode = "a") + recvrequest("NLST", temp, *argv, mode, 0, 0); + if ((code / 100) != COMPLETE) { + if (errbuf != NULL) + *errbuf = reply_string; + } + if (doswitch) + pswitch(!proxy); + verbose = oldverbose; + hash = oldhash; + progress = oldprogress; + ftemp = fopen(temp, "r"); + (void)unlink(temp); + if (ftemp == NULL) { + if (errbuf == NULL) + fputs( + "can't find list of remote files, oops.\n", + ttyout); + else + *errbuf = + "can't find list of remote files, oops."; + return (NULL); + } + } + if (fgets(buf, sizeof(buf), ftemp) == NULL) { + (void)fclose(ftemp); + ftemp = NULL; + return (NULL); + } + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + return (buf); +} + +/* + * 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. + * Returns NULL on error, or a pointer to a buffer containing the filename + * that's the caller's responsiblity to free(3) when finished with. + */ +char * +globulize(const char *pattern) +{ + glob_t gl; + int flags; + char *p; + + if (!doglob) + return (xstrdup(pattern)); + + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; + memset(&gl, 0, sizeof(gl)); + if (glob(pattern, flags, NULL, &gl) || gl.gl_pathc == 0) { + warnx("%s: not found", pattern); + globfree(&gl); + return (NULL); + } + p = xstrdup(gl.gl_pathv[0]); + globfree(&gl); + return (p); +} + +/* + * determine size of remote file + */ +off_t +remotesize(const char *file, int noisy) +{ + int overbose, r; + off_t size; + + overbose = verbose; + size = -1; + if (debug == 0) + verbose = -1; + if (! features[FEAT_SIZE]) { + if (noisy) + fprintf(ttyout, + "SIZE is not supported by remote server.\n"); + goto cleanup_remotesize; + } + r = command("SIZE %s", file); + if (r == COMPLETE) { + char *cp, *ep; + + cp = strchr(reply_string, ' '); + if (cp != NULL) { + cp++; + size = STRTOLL(cp, &ep, 10); + if (*ep != '\0' && !isspace((unsigned char)*ep)) + size = -1; + } + } else { + if (r == ERROR && code == 500 && features[FEAT_SIZE] == -1) + features[FEAT_SIZE] = 0; + if (noisy && debug == 0) { + fputs(reply_string, ttyout); + putc('\n', ttyout); + } + } + cleanup_remotesize: + verbose = overbose; + return (size); +} + +/* + * determine last modification time (in GMT) of remote file + */ +time_t +remotemodtime(const char *file, int noisy) +{ + int overbose, ocode, r; + time_t rtime; + + overbose = verbose; + ocode = code; + rtime = -1; + if (debug == 0) + verbose = -1; + if (! features[FEAT_MDTM]) { + if (noisy) + fprintf(ttyout, + "MDTM is not supported by remote server.\n"); + goto cleanup_parse_time; + } + r = command("MDTM %s", file); + if (r == COMPLETE) { + struct tm timebuf; + char *timestr, *frac; + int yy, mo, day, hour, min, sec; + + /* + * time-val = 14DIGIT [ "." 1*DIGIT ] + * YYYYMMDDHHMMSS[.sss] + * mdtm-response = "213" SP time-val CRLF / error-response + */ + timestr = reply_string + 4; + + /* + * parse fraction. + * XXX: ignored for now + */ + frac = strchr(timestr, '\r'); + if (frac != NULL) + *frac = '\0'; + frac = strchr(timestr, '.'); + if (frac != NULL) + *frac++ = '\0'; + if (strlen(timestr) == 15 && strncmp(timestr, "191", 3) == 0) { + /* + * XXX: Workaround for lame ftpd's that return + * `19100' instead of `2000' + */ + fprintf(ttyout, + "Y2K warning! Incorrect time-val `%s' received from server.\n", + timestr); + timestr++; + timestr[0] = '2'; + timestr[1] = '0'; + fprintf(ttyout, "Converted to `%s'\n", timestr); + } + if (strlen(timestr) != 14 || + sscanf(timestr, "%04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec) != 6) { + bad_parse_time: + fprintf(ttyout, "Can't parse time `%s'.\n", timestr); + goto cleanup_parse_time; + } + memset(&timebuf, 0, sizeof(timebuf)); + timebuf.tm_sec = sec; + timebuf.tm_min = min; + timebuf.tm_hour = hour; + timebuf.tm_mday = day; + timebuf.tm_mon = mo - 1; + timebuf.tm_year = yy - TM_YEAR_BASE; + timebuf.tm_isdst = -1; + rtime = timegm(&timebuf); + if (rtime == -1) { + if (noisy || debug != 0) + goto bad_parse_time; + else + goto cleanup_parse_time; + } else if (debug) + fprintf(ttyout, "parsed date as: %s", ctime(&rtime)); + } else { + if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1) + features[FEAT_MDTM] = 0; + if (noisy && debug == 0) { + fputs(reply_string, ttyout); + putc('\n', ttyout); + } + } + cleanup_parse_time: + verbose = overbose; + if (rtime == -1) + code = ocode; + return (rtime); +} + +/* + * Update global `localcwd', which contains the state of the local cwd + */ +void +updatelocalcwd(void) +{ + + if (getcwd(localcwd, sizeof(localcwd)) == NULL) + localcwd[0] = '\0'; + if (debug) + fprintf(ttyout, "got localcwd as `%s'\n", localcwd); +} + +/* + * Update global `remotecwd', which contains the state of the remote cwd + */ +void +updateremotecwd(void) +{ + int overbose, ocode, i; + char *cp; + + overbose = verbose; + ocode = code; + if (debug == 0) + verbose = -1; + if (command("PWD") != COMPLETE) + goto badremotecwd; + cp = strchr(reply_string, ' '); + if (cp == NULL || cp[0] == '\0' || cp[1] != '"') + goto badremotecwd; + cp += 2; + for (i = 0; *cp && i < sizeof(remotecwd) - 1; i++, cp++) { + if (cp[0] == '"') { + if (cp[1] == '"') + cp++; + else + break; + } + remotecwd[i] = *cp; + } + remotecwd[i] = '\0'; + if (debug) + fprintf(ttyout, "got remotecwd as `%s'\n", remotecwd); + goto cleanupremotecwd; + badremotecwd: + remotecwd[0]='\0'; + cleanupremotecwd: + verbose = overbose; + code = ocode; +} + +/* + * Ensure file is in or under dir. + * Returns 1 if so, 0 if not (or an error occurred). + */ +int +fileindir(const char *file, const char *dir) +{ + char realfile[PATH_MAX+1]; + size_t dirlen; + + if (realpath(file, realfile) == NULL) { + warn("Unable to determine real path of `%s'", file); + return 0; + } + if (realfile[0] != '/') /* relative result */ + return 1; + dirlen = strlen(dir); +#if 0 +printf("file %s realfile %s dir %s [%d]\n", file, realfile, dir, dirlen); +#endif + if (strncmp(realfile, dir, dirlen) == 0 && realfile[dirlen] == '/') + return 1; + return 0; +} + +/* + * List words in stringlist, vertically arranged + */ +void +list_vertical(StringList *sl) +{ + int i, j, w; + int columns, width, lines; + char *p; + + width = 0; + + for (i = 0 ; i < sl->sl_cur ; i++) { + w = strlen(sl->sl_str[i]); + if (w > width) + width = w; + } + width = (width + 8) &~ 7; + + columns = ttywidth / width; + if (columns == 0) + columns = 1; + lines = (sl->sl_cur + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + p = sl->sl_str[j * lines + i]; + if (p) + fputs(p, ttyout); + if (j * lines + i + lines >= sl->sl_cur) { + putc('\n', ttyout); + break; + } + w = strlen(p); + while (w < width) { + w = (w + 8) &~ 7; + (void)putc('\t', ttyout); + } + } + } +} + +/* + * Update the global ttywidth value, using TIOCGWINSZ. + */ +void +setttywidth(int a) +{ + struct winsize winsize; + int oerrno = errno; + + if (ioctl(fileno(ttyout), TIOCGWINSZ, &winsize) != -1 && + winsize.ws_col != 0) + ttywidth = winsize.ws_col; + else + ttywidth = 80; + errno = oerrno; +} + +/* + * Change the rate limit up (SIGUSR1) or down (SIGUSR2) + */ +void +crankrate(int sig) +{ + + switch (sig) { + case SIGUSR1: + if (rate_get) + rate_get += rate_get_incr; + if (rate_put) + rate_put += rate_put_incr; + break; + case SIGUSR2: + if (rate_get && rate_get > rate_get_incr) + rate_get -= rate_get_incr; + if (rate_put && rate_put > rate_put_incr) + rate_put -= rate_put_incr; + break; + default: + err(1, "crankrate invoked with unknown signal: %d", sig); + } +} + + +/* + * Setup or cleanup EditLine structures + */ +#ifndef NO_EDITCOMPLETE +void +controlediting(void) +{ + if (editing && el == NULL && hist == NULL) { + HistEvent ev; + int editmode; + + el = el_init(getprogname(), stdin, ttyout, stderr); + /* init editline */ + hist = history_init(); /* init the builtin history */ + history(hist, &ev, H_SETSIZE, 100);/* remember 100 events */ + el_set(el, EL_HIST, history, hist); /* use history */ + + el_set(el, EL_EDITOR, "emacs"); /* default editor is emacs */ + el_set(el, EL_PROMPT, prompt); /* set the prompt functions */ + el_set(el, EL_RPROMPT, rprompt); + + /* add local file completion, bind to TAB */ + el_set(el, EL_ADDFN, "ftp-complete", + "Context sensitive argument completion", + complete); + el_set(el, EL_BIND, "^I", "ftp-complete", NULL); + el_source(el, NULL); /* read ~/.editrc */ + if ((el_get(el, EL_EDITMODE, &editmode) != -1) && editmode == 0) + editing = 0; /* the user doesn't want editing, + * so disable, and let statement + * below cleanup */ + else + el_set(el, EL_SIGNAL, 1); + } + if (!editing) { + if (hist) { + history_end(hist); + hist = NULL; + } + if (el) { + el_end(el); + el = NULL; + } + } +} +#endif /* !NO_EDITCOMPLETE */ + +/* + * Convert the string `arg' to an int, which may have an optional SI suffix + * (`b', `k', `m', `g'). Returns the number for success, -1 otherwise. + */ +int +strsuftoi(const char *arg) +{ + char *cp; + long val; + + if (!isdigit((unsigned char)arg[0])) + return (-1); + + val = strtol(arg, &cp, 10); + if (cp != NULL) { + if (cp[0] != '\0' && cp[1] != '\0') + return (-1); + switch (tolower((unsigned char)cp[0])) { + case '\0': + case 'b': + break; + case 'k': + val <<= 10; + break; + case 'm': + val <<= 20; + break; + case 'g': + val <<= 30; + break; + default: + return (-1); + } + } + if (val < 0 || val > INT_MAX) + return (-1); + + return (val); +} + +/* + * Set up socket buffer sizes before a connection is made. + */ +void +setupsockbufsize(int sock) +{ + + if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, + (void *)&sndbuf_size, sizeof(sndbuf_size)) == -1) + warn("unable to set sndbuf size %d", sndbuf_size); + + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + (void *)&rcvbuf_size, sizeof(rcvbuf_size)) == -1) + warn("unable to set rcvbuf size %d", rcvbuf_size); +} + +/* + * Copy characters from src into dst, \ quoting characters that require it + */ +void +ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen) +{ + int di, si; + + for (di = si = 0; + src[si] != '\0' && di < dstlen && si < srclen; + di++, si++) { + switch (src[si]) { + case '\\': + case ' ': + case '\t': + case '\r': + case '\n': + case '"': + dst[di++] = '\\'; + if (di >= dstlen) + break; + /* FALLTHROUGH */ + default: + dst[di] = src[si]; + } + } + dst[di] = '\0'; +} + +/* + * Copy src into buf (which is len bytes long), expanding % sequences. + */ +void +formatbuf(char *buf, size_t len, const char *src) +{ + const char *p; + char *p2, *q; + int i, op, updirs, pdirs; + +#define ADDBUF(x) do { \ + if (i >= len - 1) \ + goto endbuf; \ + buf[i++] = (x); \ + } while (0) + + p = src; + for (i = 0; *p; p++) { + if (*p != '%') { + ADDBUF(*p); + continue; + } + p++; + + switch (op = *p) { + + case '/': + case '.': + case 'c': + p2 = connected ? remotecwd : ""; + updirs = pdirs = 0; + + /* option to determine fixed # of dirs from path */ + if (op == '.' || op == 'c') { + int skip; + + q = p2; + while (*p2) /* calc # of /'s */ + if (*p2++ == '/') + updirs++; + if (p[1] == '0') { /* print <x> or ... */ + pdirs = 1; + p++; + } + if (p[1] >= '1' && p[1] <= '9') { + /* calc # to skip */ + skip = p[1] - '0'; + p++; + } else + skip = 1; + + updirs -= skip; + while (skip-- > 0) { + while ((p2 > q) && (*p2 != '/')) + p2--; /* back up */ + if (skip && p2 > q) + p2--; + } + if (*p2 == '/' && p2 != q) + p2++; + } + + if (updirs > 0 && pdirs) { + if (i >= len - 5) + break; + if (op == '.') { + ADDBUF('.'); + ADDBUF('.'); + ADDBUF('.'); + } else { + ADDBUF('/'); + ADDBUF('<'); + if (updirs > 9) { + ADDBUF('9'); + ADDBUF('+'); + } else + ADDBUF('0' + updirs); + ADDBUF('>'); + } + } + for (; *p2; p2++) + ADDBUF(*p2); + break; + + case 'M': + case 'm': + for (p2 = connected && username ? username : "-"; + *p2 ; p2++) { + if (op == 'm' && *p2 == '.') + break; + ADDBUF(*p2); + } + break; + + case 'n': + for (p2 = connected ? username : "-"; *p2 ; p2++) + ADDBUF(*p2); + break; + + case '%': + ADDBUF('%'); + break; + + default: /* display unknown codes literally */ + ADDBUF('%'); + ADDBUF(op); + break; + + } + } + endbuf: + buf[i] = '\0'; +} + +/* + * Parse `port' into a TCP port number, defaulting to `defport' if `port' is + * an unknown service name. If defport != -1, print a warning upon bad parse. + */ +int +parseport(const char *port, int defport) +{ + int rv; + long nport; + char *p, *ep; + + p = xstrdup(port); + nport = strtol(p, &ep, 10); + if (*ep != '\0' && ep == p) { + struct servent *svp; + + svp = getservbyname(port, "tcp"); + if (svp == NULL) { + badparseport: + if (defport != -1) + warnx("Unknown port `%s', using port %d", + port, defport); + rv = defport; + } else + rv = ntohs(svp->s_port); + } else if (nport < 1 || nport > MAX_IN_PORT_T || *ep != '\0') + goto badparseport; + else + rv = nport; + free(p); + return (rv); +} + +/* + * Determine if given string is an IPv6 address or not. + * Return 1 for yes, 0 for no + */ +int +isipv6addr(const char *addr) +{ + int rv = 0; +#ifdef INET6 + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_INET6; + hints.ai_socktype = SOCK_DGRAM; /*dummy*/ + hints.ai_flags = AI_NUMERICHOST; + if (getaddrinfo(addr, "0", &hints, &res) != 0) + rv = 0; + else { + rv = 1; + freeaddrinfo(res); + } + if (debug) + fprintf(ttyout, "isipv6addr: got %d for %s\n", rv, addr); +#endif + return (rv == 1) ? 1 : 0; +} + + +/* + * Internal version of connect(2); sets socket buffer sizes first and + * supports a connection timeout using a non-blocking connect(2) with + * a poll(2). + * Socket fcntl flags are temporarily updated to include O_NONBLOCK; + * these will not be reverted on connection failure. + * Returns -1 upon failure (with errno set to the problem), or 0 on success. + */ +int +xconnect(int sock, const struct sockaddr *name, socklen_t namelen) +{ + int flags, rv, timeout, error; + socklen_t slen; + struct timeval endtime, now, td; + struct pollfd pfd[1]; + + setupsockbufsize(sock); + + if ((flags = fcntl(sock, F_GETFL, 0)) == -1) + return -1; /* get current socket flags */ + if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) + return -1; /* set non-blocking connect */ + + /* NOTE: we now must restore socket flags on successful exit */ + + pfd[0].fd = sock; + pfd[0].events = POLLIN|POLLOUT; + + if (quit_time > 0) { /* want a non default timeout */ + (void)gettimeofday(&endtime, NULL); + endtime.tv_sec += quit_time; /* determine end time */ + } + + rv = connect(sock, name, namelen); /* inititate the connection */ + if (rv == -1) { /* connection error */ + if (errno != EINPROGRESS) /* error isn't "please wait" */ + return -1; + + /* connect EINPROGRESS; wait */ + do { + if (quit_time > 0) { /* determine timeout */ + (void)gettimeofday(&now, NULL); + timersub(&endtime, &now, &td); + timeout = td.tv_sec * 1000 + td.tv_usec/1000; + if (timeout < 0) + timeout = 0; + } else { + timeout = INFTIM; + } + pfd[0].revents = 0; + rv = xpoll(pfd, 1, timeout); + /* loop until poll ! EINTR */ + } while (rv == -1 && errno == EINTR); + + if (rv == 0) { /* poll (connect) timed out */ + errno = ETIMEDOUT; + return -1; + } + + if (rv == -1) { /* poll error */ + return -1; + } else if (pfd[0].revents & (POLLIN|POLLOUT)) { + slen = sizeof(error); /* OK, or pending error */ + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, + &error, &slen) == -1) + return -1; /* Solaris pending error */ + if (error != 0) { + errno = error; /* BSD pending error */ + return -1; + } + } else { + errno = EBADF; /* this shouldn't happen ... */ + return -1; + } + } + + if (fcntl(sock, F_SETFL, flags) == -1) /* restore socket flags */ + return -1; + return 0; +} + +/* + * Internal version of listen(2); sets socket buffer sizes first. + */ +int +xlisten(int sock, int backlog) +{ + + setupsockbufsize(sock); + return (listen(sock, backlog)); +} + +/* + * Internal version of poll(2), to allow reimplementation by select(2) + * on platforms without the former. + */ +int +xpoll(struct pollfd *fds, int nfds, int timeout) +{ + return poll(fds, nfds, timeout); +} + +/* + * malloc() with inbuilt error checking + */ +void * +xmalloc(size_t size) +{ + void *p; + + p = malloc(size); + if (p == NULL) + err(1, "Unable to allocate %ld bytes of memory", (long)size); + return (p); +} + +/* + * sl_init() with inbuilt error checking + */ +StringList * +xsl_init(void) +{ + StringList *p; + + p = sl_init(); + if (p == NULL) + err(1, "Unable to allocate memory for stringlist"); + return (p); +} + +/* + * sl_add() with inbuilt error checking + */ +void +xsl_add(StringList *sl, char *i) +{ + + if (sl_add(sl, i) == -1) + err(1, "Unable to add `%s' to stringlist", i); +} + +/* + * strdup() with inbuilt error checking + */ +char * +xstrdup(const char *str) +{ + char *s; + + if (str == NULL) + errx(1, "xstrdup() called with NULL argument"); + s = strdup(str); + if (s == NULL) + err(1, "Unable to allocate memory for string copy"); + return (s); +} diff --git a/contrib/tnftp/src/version.h b/contrib/tnftp/src/version.h new file mode 100644 index 0000000..7b69df1 --- /dev/null +++ b/contrib/tnftp/src/version.h @@ -0,0 +1,44 @@ +/* $NetBSD: version.h,v 1.50 2005/05/14 15:26:43 lukem Exp $ */ +/*- + * Copyright (c) 1999-2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn. + * + * 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 NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + */ + +#ifndef FTP_PRODUCT +#define FTP_PRODUCT "NetBSD-ftp" +#endif + +#ifndef FTP_VERSION +#define FTP_VERSION "20050514" +#endif diff --git a/contrib/tnftp/todo b/contrib/tnftp/todo new file mode 100644 index 0000000..4863815 --- /dev/null +++ b/contrib/tnftp/todo @@ -0,0 +1,25 @@ +$Id: todo,v 1.30 2002/06/10 08:08:53 lukem Exp $ + +update NEWS, README, ... + +at end of configure, show summary of options used and features found + +if socks is defined, disable ipv6 and use own getaddrinfo()/getnameinfo() +(for tron) + +add locale autoconf checks + +AC_CHECK_SIZEOF(off_t, 0) doesn't work on FreeBSD 4.0 because the +test doesn't include <sys/types.h>. fix autoconf? + +in configure, check for ansi c compiler and barf if it fails + +check if we need #defines for memcpy() et al + +check for utimes() decls [which system?] + +possibly install editline.3 and editrc.5 + +system specific tests (to remove need for manual intervention): +- sunos4 + LIBS+= -lresolv |