From bfc02740ac2d5248ff4f0a4848608db55faed1e4 Mon Sep 17 00:00:00 2001 From: John Marino Date: Wed, 4 Nov 2015 18:22:36 +0100 Subject: [PATCH] contrib/tnftp: Delete entire contents prior to merge Due to a file hierarchy change, merging with the vendor branch will very difficult. It's easier to wipe everything and resync to the vendor branch manually (auto-merge will fail everywhere). I've the local modifications although half of them are cruft from various upgrades. --- contrib/tnftp/cmds.c | 2796 ----------------------------------- contrib/tnftp/cmdtab.c | 307 ---- contrib/tnftp/complete.c | 432 ------ contrib/tnftp/domacro.c | 145 -- contrib/tnftp/extern.h | 248 ---- contrib/tnftp/fetch.c | 2013 ------------------------- contrib/tnftp/ftp.1 | 2421 ------------------------------ contrib/tnftp/ftp.c | 2153 --------------------------- contrib/tnftp/ftp_var.h | 355 ----- contrib/tnftp/main.c | 1057 ------------- contrib/tnftp/progressbar.c | 472 ------ contrib/tnftp/progressbar.h | 92 -- contrib/tnftp/ruserpass.c | 318 ---- contrib/tnftp/ssl.c | 609 -------- contrib/tnftp/ssl.h | 63 - contrib/tnftp/util.c | 1542 ------------------- contrib/tnftp/version.h | 38 - 17 files changed, 15061 deletions(-) delete mode 100644 contrib/tnftp/cmds.c delete mode 100644 contrib/tnftp/cmdtab.c delete mode 100644 contrib/tnftp/complete.c delete mode 100644 contrib/tnftp/domacro.c delete mode 100644 contrib/tnftp/extern.h delete mode 100644 contrib/tnftp/fetch.c delete mode 100644 contrib/tnftp/ftp.1 delete mode 100644 contrib/tnftp/ftp.c delete mode 100644 contrib/tnftp/ftp_var.h delete mode 100644 contrib/tnftp/main.c delete mode 100644 contrib/tnftp/progressbar.c delete mode 100644 contrib/tnftp/progressbar.h delete mode 100644 contrib/tnftp/ruserpass.c delete mode 100644 contrib/tnftp/ssl.c delete mode 100644 contrib/tnftp/ssl.h delete mode 100644 contrib/tnftp/util.c delete mode 100644 contrib/tnftp/version.h diff --git a/contrib/tnftp/cmds.c b/contrib/tnftp/cmds.c deleted file mode 100644 index d235fd1008..0000000000 --- a/contrib/tnftp/cmds.c +++ /dev/null @@ -1,2796 +0,0 @@ -/* $NetBSD: cmds.c,v 1.135 2012/12/22 16:57:09 christos Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94"; -#else -__RCSID("$NetBSD: cmds.c,v 1.135 2012/12/22 16:57:09 christos Exp $"); -#endif -#endif /* not lint */ - -/* - * FTP User Program -- Command Routines. - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ftp_var.h" -#include "version.h" - -static struct types { - const char *t_name; - const char *t_mode; - int t_type; - const 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, NULL, 0, NULL } -}; - -static sigjmp_buf jabort; - -static int confirm(const char *, const char *); -__dead static void mintr(int); -static void mabort(const char *); -static void set_type(const char *); - -static const char *doprocess(char *, size_t, const char *, int, int, int); -static const char *domap(char *, size_t, const char *); -static const char *docase(char *, size_t, const char *); -static const char *dotrans(char *, size_t, const char *); - -/* - * Confirm if "cmd" is to be performed upon "file". - * If "file" is NULL, generate a "Continue with" prompt instead. - */ -static int -confirm(const char *cmd, const char *file) -{ - const char *errormsg; - char cline[BUFSIZ]; - const char *promptleft, *promptright; - - if (!interactive || confirmrest) - return (1); - if (file == NULL) { - promptleft = "Continue with"; - promptright = cmd; - } else { - promptleft = cmd; - promptright = file; - } - while (1) { - fprintf(ttyout, "%s %s [anpqy?]? ", promptleft, promptright); - (void)fflush(ttyout); - if (get_line(stdin, cline, sizeof(cline), &errormsg) < 0) { - mflag = 0; - fprintf(ttyout, "%s; %s aborted\n", errormsg, cmd); - return (0); - } - switch (tolower((unsigned char)*cline)) { - 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", cmd); - /* 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; - - if (argc == 0 || argc > 2) { - const char *sep; - - UPRINTF("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; - } - set_type(argv[1]); -} - -void -set_type(const char *ttype) -{ - struct types *p; - int comret; - - for (p = types; p->t_name; p++) - if (strcmp(ttype, p->t_name) == 0) - break; - if (p->t_name == 0) { - fprintf(ttyout, "%s: unknown mode.\n", ttype); - 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 (ftp_debug == 0 && show == 0) - verbose = 0; - for (p = types; p->t_name; p++) - if (newtype == p->t_type) - break; - if (p->t_name == 0) { - errx(1, "changetype: unknown type %d", newtype); - } - 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; -} - -/* - * Set binary transfer type. - */ -/*VARARGS*/ -void -setbinary(int argc, char *argv[]) -{ - - if (argc == 0) { - UPRINTF("usage: %s\n", argv[0]); - code = -1; - return; - } - set_type("binary"); -} - -/* - * Set ascii transfer type. - */ -/*VARARGS*/ -void -setascii(int argc, char *argv[]) -{ - - if (argc == 0) { - UPRINTF("usage: %s\n", argv[0]); - code = -1; - return; - } - set_type("ascii"); -} - -/* - * Set tenex transfer type. - */ -/*VARARGS*/ -void -settenex(int argc, char *argv[]) -{ - - if (argc == 0) { - UPRINTF("usage: %s\n", argv[0]); - code = -1; - return; - } - set_type("tenex"); -} - -/* - * Set file transfer mode. - */ -/*ARGSUSED*/ -void -setftmode(int argc, char *argv[]) -{ - - if (argc != 2) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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]; - const 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: - UPRINTF("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"))) { - UPRINTF("usage: %s local-files\n", argv[0]); - code = -1; - return; - } - mflag = 1; - oldintr = xsignal(SIGINT, mintr); - if (sigsetjmp(jabort, 1)) - mabort(argv[0]); - 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(argv[0], NULL)) { - 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(argv[0], NULL)) { - 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("Glob pattern `%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(argv[0], NULL)) { - mflag++; - } - interactive = ointer; - } - } - } - globfree(&gl); - } - cleanupmput: - (void)xsignal(SIGINT, oldintr); - mflag = 0; -} - -void -reget(int argc, char *argv[]) -{ - - (void)getit(argc, argv, 1, restart_point ? "r+" : "a"); -} - -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 *gmode) -{ - 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: - UPRINTF("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) { - if (errno != ENOENT) { - warn("Can't stat `%s'", locfile); - goto freegetit; - } - restart_point = 0; - } - else - 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, gmode, - remfile != argv[1] || locfile != argv[2], loc); - restart_point = 0; - freegetit: - (void)free(olocfile); - return (rval); -} - -/* ARGSUSED */ -static void -mintr(int signo) -{ - - alarmtimer(0); - if (fromatty) - write(fileno(ttyout), "\n", 1); - siglongjmp(jabort, 1); -} - -static void -mabort(const char *cmd) -{ - int ointer, oconf; - - if (mflag && fromatty) { - ointer = interactive; - oconf = confirmrest; - interactive = 1; - confirmrest = 0; - if (confirm(cmd, NULL)) { - 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 volatile restartit; - - if (argc == 0 || - (argc == 1 && !another(&argc, &argv, "remote-files"))) { - UPRINTF("usage: %s remote-files\n", argv[0]); - code = -1; - return; - } - 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(argv[0]); - 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("Can't 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(argv[0], NULL)) - 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[]) -{ - const char *gmode; - FILE *fp; - char buf[MAXPATHLEN], cmdbuf[MAX_C_NAME]; - - if (argc != 2) { - UPRINTF("usage: %s localfile\n", argv[0]); - code = -1; - return; - } - - fp = fopen(argv[1], "r"); - if (fp == NULL) { - fprintf(ttyout, "Can't open source file %s\n", argv[1]); - code = -1; - return; - } - - (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf)); - argv[0] = cmdbuf; - gmode = restart_point ? "r+" : "w"; - - while (get_line(fp, buf, sizeof(buf), NULL) >= 0) { - if (buf[0] == '\0') - continue; - argv[1] = buf; - (void)getit(argc, argv, 0, gmode); - } - fclose(fp); -} - -const char * -onoff(int val) -{ - - return (val ? "on" : "off"); -} - -/* - * Show status. - */ -/*ARGSUSED*/ -void -status(int argc, char *argv[]) -{ - - if (argc == 0) { - UPRINTF("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, "Use of EPSV/EPRT cmds for IPv6: %s%s.\n", onoff(epsv6), - epsv6bad ? " (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 3) { - UPRINTF( - "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 = ftp_strdup(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) { - UPRINTF("usage: %s [ on | off | debuglevel ]\n", argv[0]); - code = -1; - return; - } else if (argc == 2) { - if (strcasecmp(argv[1], "on") == 0) - ftp_debug = 1; - else if (strcasecmp(argv[1], "off") == 0) - ftp_debug = 0; - else { - int val; - - val = strsuftoi(argv[1]); - if (val < 0) { - fprintf(ttyout, "%s: bad debugging value.\n", - argv[1]); - code = -1; - return; - } - ftp_debug = val; - } - } else - ftp_debug = !ftp_debug; - if (ftp_debug) - options |= SO_DEBUG; - else - options &= ~SO_DEBUG; - fprintf(ttyout, "Debugging %s (ftp_debug=%d).\n", onoff(ftp_debug), ftp_debug); - code = ftp_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"))) { - UPRINTF("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) { - UPRINTF("usage: %s [local-directory]\n", argv[0]); - return; - } - if ((locdir = globulize(argv[1])) == NULL) - return; - if (chdir(locdir) == -1) - warn("Can't chdir `%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"))) { - UPRINTF("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"))) { - UPRINTF("usage: %s [remote-files]\n", argv[0]); - code = -1; - return; - } - mflag = 1; - oldintr = xsignal(SIGINT, mintr); - if (sigsetjmp(jabort, 1)) - mabort(argv[0]); - 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(argv[0], NULL)) { - 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: - UPRINTF("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 - * pmlsd MLSD |$PAGER - */ -void -ls(int argc, char *argv[]) -{ - const char *cmd; - char *remdir, *locbuf; - const char *locfile; - int pagecmd, mlsdcmd; - - remdir = NULL; - locbuf = NULL; - locfile = "-"; - 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) - UPRINTF("usage: %s [remote-path]\n", argv[0]); - else - UPRINTF("usage: %s [remote-path [local-file]]\n", - argv[0]); - code = -1; - goto freels; - } - - if (pagecmd) { - const char *p; - size_t len; - - p = getoptionvalue("pager"); - if (EMPTYSTRING(p)) - p = DEFAULTPAGER; - len = strlen(p) + 2; - locbuf = ftp_malloc(len); - locbuf[0] = '|'; - (void)strlcpy(locbuf + 1, p, len - 1); - locfile = locbuf; - } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') { - if ((locbuf = globulize(locfile)) == NULL || - !confirm("output to local-file:", locbuf)) { - code = -1; - goto freels; - } - locfile = locbuf; - } - recvrequest(cmd, locfile, remdir, "w", 0, 0); - freels: - if (locbuf) - (void)free(locbuf); -} - -/* - * Get a directory listing of multiple remote files. - */ -void -mls(int argc, char *argv[]) -{ - sigfunc oldintr; - int ointer, i; - int volatile dolist; - char * volatile dest, *odest; - const char *lmode; - - if (argc == 0) - goto usage; - if (argc < 2 && !another(&argc, &argv, "remote-files")) - goto usage; - if (argc < 3 && !another(&argc, &argv, "local-file")) { - usage: - UPRINTF("usage: %s remote-files local-file\n", argv[0]); - code = -1; - return; - } - odest = dest = argv[argc - 1]; - argv[argc - 1] = NULL; - if (strcmp(dest, "-") && *dest != '|') - if (((dest = globulize(dest)) == NULL) || - !confirm("output to local-file:", dest)) { - code = -1; - return; - } - dolist = strcmp(argv[0], "mls"); - mflag = 1; - oldintr = xsignal(SIGINT, mintr); - if (sigsetjmp(jabort, 1)) - mabort(argv[0]); - for (i = 1; mflag && i < argc-1 && connected; i++) { - lmode = (i == 1) ? "w" : "a"; - recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], lmode, - 0, 0); - if (!mflag && fromatty) { - ointer = interactive; - interactive = 1; - if (confirm(argv[0], NULL)) { - 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]; - const char *shellp, *namep; - int wait_status; - - if (argc == 0) { - UPRINTF("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); - shellp = getenv("SHELL"); - if (shellp == NULL) - shellp = _PATH_BSHELL; - namep = strrchr(shellp, '/'); - if (namep == NULL) - namep = shellp; - else - namep++; - (void)strlcpy(shellnam, namep, sizeof(shellnam)); - if (ftp_debug) { - fputs(shellp, ttyout); - putc('\n', ttyout); - } - if (argc > 1) { - execl(shellp, shellnam, "-c", altarg, (char *)0); - } - else { - execl(shellp, shellnam, (char *)0); - } - warn("Can't execute `%s'", shellp); - code = -1; - exit(1); - } - if (pid > 0) - while (wait(&wait_status) != pid) - ; - (void)xsignal(SIGINT, oldintr); - if (pid == -1) { - warn("Can't fork a subshell; try again later"); - code = -1; - } else - code = 0; -} - -/* - * Send new user information (re-login) - */ -void -user(int argc, char *argv[]) -{ - char *password; - char emptypass[] = ""; - int n, aflag = 0; - - if (argc == 0) - goto usage; - if (argc < 2) - (void)another(&argc, &argv, "username"); - if (argc < 2 || argc > 4) { - usage: - UPRINTF("usage: %s username [password [account]]\n", - argv[0]); - code = -1; - return; - } - n = command("USER %s", argv[1]); - if (n == CONTINUE) { - if (argc < 3) { - password = getpass("Password: "); - if (password == NULL) - password = emptypass; - } else { - password = argv[2]; - } - n = command("PASS %s", password); - memset(password, 0, strlen(password)); - } - if (n == CONTINUE) { - aflag++; - if (argc < 4) { - password = getpass("Account: "); - if (password == NULL) - password = emptypass; - } else { - password = argv[3]; - } - n = command("ACCT %s", password); - memset(password, 0, strlen(password)); - } - if (n != COMPLETE) { - fputs("Login failed.\n", ttyout); - return; - } - if (!aflag && argc == 4) { - password = argv[3]; - (void)command("ACCT %s", password); - memset(password, 0, strlen(password)); - } - connected = -1; - getremoteinfo(); -} - -/* - * Print working directory on remote machine. - */ -/*VARARGS*/ -void -pwd(int argc, char *argv[]) -{ - - code = -1; - if (argc != 1) { - UPRINTF("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) { - UPRINTF("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"))) { - UPRINTF("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"))) { - UPRINTF("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"))) { - UPRINTF("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"))){ - UPRINTF("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: - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("usage: %s\n", argv[0]); - code = -1; - return; - } - if (!connected) - return; - (void)command("QUIT"); - cleanuppeer(); -} - -void -account(int argc, char *argv[]) -{ - char *ap; - char emptypass[] = ""; - - if (argc == 0 || argc > 2) { - UPRINTF("usage: %s [password]\n", argv[0]); - code = -1; - return; - } - else if (argc == 2) - ap = argv[1]; - else { - ap = getpass("Account:"); - if (ap == NULL) - ap = emptypass; - } - (void)command("ACCT %s", ap); - memset(ap, 0, strlen(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; - char cmdbuf[MAX_C_NAME]; - - if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) { - UPRINTF("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); - (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf)); - argv[1] = cmdbuf; - (*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) { - UPRINTF("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 >= (ptrdiff_t)(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) { - UPRINTF("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: - UPRINTF("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 -setepsv6(int argc, char *argv[]) -{ - code = togglevar(argc, argv, &epsv6, - verbose ? "EPSV/EPRT on IPv6" : NULL); - epsv6bad = 0; -} - -void -setepsv(int argc, char*argv[]) -{ - setepsv4(argc,argv); - setepsv6(argc,argv); -} - -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) - UPRINTF( - "usage: %s (all|get|put),maximum-bytes[,increment-bytes]]\n", - argv[0]); - else - UPRINTF( - "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) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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: - UPRINTF("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"))) { - UPRINTF("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"))) { - UPRINTF("usage: %s remote-file\n", argv[0]); - code = -1; - return; - } - mtime = remotemodtime(argv[1], 1); - if (mtime != -1) - fprintf(ttyout, "%s\t%s", argv[1], - rfc2822time(localtime(&mtime))); - code = (mtime > 0); -} - -/* - * Show status on remote machine - */ -void -rmtstatus(int argc, char *argv[]) -{ - - if (argc == 0) { - UPRINTF("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[]) -{ - size_t len; - const char *p; - char *pager, *locfile; - - if (argc == 0 || argc > 2 || - (argc == 1 && !another(&argc, &argv, "local-file"))) { - UPRINTF("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 = ftp_malloc(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; - size_t len; - const char *p; - char *pager; - - if (argc == 0 || argc > 2 || - (argc == 1 && !another(&argc, &argv, "remote-file"))) { - UPRINTF("usage: %s remote-file\n", argv[0]); - code = -1; - return; - } - p = getoptionvalue("pager"); - if (EMPTYSTRING(p)) - p = DEFAULTPAGER; - len = strlen(p) + 2; - pager = ftp_malloc(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: - UPRINTF("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)) { - UPRINTF("usage: %s [option value]\n", argv[0]); - return; - } - -#define OPTIONINDENT ((int) sizeof("https_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 { - set_option(argv[1], argv[2], 1); - } - code = 0; -} - -void -set_option(const char * option, const char * value, int doverbose) -{ - struct option *o; - - o = getoption(option); - if (o == NULL) { - fprintf(ttyout, "No such option `%s'.\n", option); - return; - } - FREEPTR(o->value); - o->value = ftp_strdup(value); - if (verbose && doverbose) - fprintf(ttyout, "Setting `%s' to `%s'.\n", - o->name, o->value); -} - -/* - * Unset an option - */ -void -unsetoption(int argc, char *argv[]) -{ - struct option *o; - - code = -1; - if (argc == 0 || argc != 2) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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) { - UPRINTF("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/cmdtab.c b/contrib/tnftp/cmdtab.c deleted file mode 100644 index 13d3f4b82c..0000000000 --- a/contrib/tnftp/cmdtab.c +++ /dev/null @@ -1,307 +0,0 @@ -/* $NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94"; -#else -__RCSID("$NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#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 epsvhelp[] = "toggle use of EPSV/EPRT on both IPv4 and IPV6 ftp"; -HSTR epsv4help[] = "toggle use of EPSV/EPRT on IPv4 ftp"; -HSTR epsv6help[] = "toggle use of EPSV/EPRT on IPv6 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 }, - { "epsv", H(epsvhelp), 0, 0, 0, CMPL0 setepsv }, - { "epsv4", H(epsv4help), 0, 0, 0, CMPL0 setepsv4 }, - { "epsv6", H(epsv6help), 0, 0, 0, CMPL0 setepsv6 }, - { "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 }, - { NULL, NULL, 0, 0, 0, CMPL0 NULL }, -}; - -struct option optiontab[] = { - { "anonpass", NULL }, - { "ftp_proxy", NULL }, - { "http_proxy", NULL }, - { "https_proxy",NULL }, - { "no_proxy", NULL }, - { "pager", NULL }, - { "prompt", NULL }, - { "rprompt", NULL }, - { NULL, NULL }, -}; diff --git a/contrib/tnftp/complete.c b/contrib/tnftp/complete.c deleted file mode 100644 index 617af07ca8..0000000000 --- a/contrib/tnftp/complete.c +++ /dev/null @@ -1,432 +0,0 @@ -/* $NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp $ */ - -/*- - * Copyright (c) 1997-2009 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. - * - * 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 -#ifndef lint -__RCSID("$NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp $"); -#endif /* not lint */ - -/* - * FTP user program - command and file completion routines - */ - -#include - -#include -#include -#include -#include -#include -#include - -#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 * const *)a, *(const char * const *)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; - size_t 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 = ftp_sl_init(); - wordlen = strlen(word); - - for (c = cmdtab; c->c_name != NULL; c++) { - if (wordlen > strlen(c->c_name)) - continue; - if (strncmp(word, c->c_name, wordlen) == 0) - ftp_sl_add(words, ftp_strdup(c->c_name)); - } - - rv = complete_ambiguous(word, list, words); - if (rv == CC_REFRESH) { - if (el_insertstr(el, " ") == -1) - rv = CC_ERROR; - } - sl_free(words, 1); - 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 = ftp_sl_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 = ftp_strdup(dp->d_name); - ftp_sl_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 = ftp_sl_init(); - wordlen = strlen(word); - - for (o = optiontab; o->name != NULL; o++) { - if (wordlen > strlen(o->name)) - continue; - if (strncmp(word, o->name, wordlen) == 0) - ftp_sl_add(words, ftp_strdup(o->name)); - } - - rv = complete_ambiguous(word, list, words); - if (rv == CC_REFRESH) { - if (el_insertstr(el, " ") == -1) - rv = CC_ERROR; - } - sl_free(words, 1); - 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; - size_t i; - unsigned char rv; - char cmdbuf[MAX_C_NAME]; - char *dummyargv[3] = { NULL, NULL, NULL }; - - (void)strlcpy(cmdbuf, "complete", sizeof(cmdbuf)); - dummyargv[0] = cmdbuf; - 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 */ - const char *emesg; - - if (dirlist != NULL) - sl_free(dirlist, 1); - dirlist = ftp_sl_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 = ftp_strdup(tcp); - ftp_sl_add(dirlist, tcp); - } - if (emesg != NULL) { - fprintf(ttyout, "\n%s\n", emesg); - return (CC_REDISPLAY); - } - (void)strlcpy(lastdir, dir, sizeof(lastdir)); - dirchange = 0; - } - - words = ftp_sl_init(); - for (i = 0; i < dirlist->sl_cur; i++) { - cp = dirlist->sl_str[i]; - if (strlen(file) > strlen(cp)) - continue; - if (strncmp(file, cp, strlen(file)) == 0) - ftp_sl_add(words, cp); - } - rv = complete_ambiguous(file, list, words); - sl_free(words, 0); - return (rv); -} - -/* - * Generic complete routine - */ -unsigned char -complete(EditLine *cel, int ch) -{ - static char word[FTPBUFLEN]; - static size_t lastc_argc, lastc_argo; - - struct cmd *c; - const LineInfo *lf; - int dolist, cmpltype; - size_t celems, len; - - lf = el_line(cel); - 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 < (size_t)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, "complete: unknown complete type `%c'", - cmpltype); - return (CC_ERROR); - } - /* NOTREACHED */ -} - -#endif /* !NO_EDITCOMPLETE */ diff --git a/contrib/tnftp/domacro.c b/contrib/tnftp/domacro.c deleted file mode 100644 index 04799bc7b9..0000000000 --- a/contrib/tnftp/domacro.c +++ /dev/null @@ -1,145 +0,0 @@ -/* $NetBSD: domacro.c,v 1.22 2009/04/12 10:18:52 lukem 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 -#ifndef lint -#if 0 -static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: domacro.c,v 1.22 2009/04/12 10:18:52 lukem Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#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; - char cmdbuf[MAX_C_NAME]; - - if ((argc == 0 && argv != NULL) || - (argc < 2 && !another(&argc, &argv, "macro name"))) { - UPRINTF("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); - } - (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf)); - margv[0] = cmdbuf; - (*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/extern.h b/contrib/tnftp/extern.h deleted file mode 100644 index e856ef4538..0000000000 --- a/contrib/tnftp/extern.h +++ /dev/null @@ -1,248 +0,0 @@ -/* $NetBSD: extern.h,v 1.80 2012/07/04 06:09:37 is Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 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 *); -int get_line(FILE *, char *, size_t, 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(const char *, const char *); -void idlecmd(int, char **); -int initconn(void); -__dead 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 macdef(int, char **); -void makeargv(void); -void makedir(int, char **); -void mdelete(int, char **); -void mget(int, char **); -void mls(int, char **); -void mlst(int, char **); -void modtime(int, char **); -void mput(int, char **); -const char *onoff(int); -void opts(int, char **); -void newer(int, char **); -void page(int, char **); -const char *parse_rfc2616time(struct tm *, const char *); -int parserate(int, char **, int); -char *prompt(void); -__dead 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, const 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 **); -const char *rfc2822time(const struct tm *); -void rmthelp(int, char **); -void rmtstatus(int, char **); -char *rprompt(void); -int ruserpass(const char *, char **, char **, 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 setepsv6(int, char **); -void setepsv(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 set_option(const char *, const char *, int); -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 user(int, char **); -int ftp_connect(int, const struct sockaddr *, socklen_t, int); -int ftp_listen(int, int); -int ftp_poll(struct pollfd *, int, int); -void *ftp_malloc(size_t); -StringList *ftp_sl_init(void); -void ftp_sl_add(StringList *, char *); -char *ftp_strdup(const char *); diff --git a/contrib/tnftp/fetch.c b/contrib/tnftp/fetch.c deleted file mode 100644 index 0a627ee27d..0000000000 --- a/contrib/tnftp/fetch.c +++ /dev/null @@ -1,2013 +0,0 @@ -/* $NetBSD: fetch.c,v 1.206 2014/10/26 16:21:59 christos Exp $ */ - -/*- - * Copyright (c) 1997-2009 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. - * - * 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 -#ifndef lint -__RCSID("$NetBSD: fetch.c,v 1.206 2014/10/26 16:21:59 christos Exp $"); -#endif /* not lint */ - -/* - * FTP User Program -- Command line file retrieval - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ssl.h" -#include "ftp_var.h" -#include "version.h" - -typedef enum { - UNKNOWN_URL_T=-1, - HTTP_URL_T, -#ifdef WITH_SSL - HTTPS_URL_T, -#endif - FTP_URL_T, - FILE_URL_T, - CLASSIC_URL_T -} url_t; - -__dead static void aborthttp(int); -__dead static void timeouthttp(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 */ -#ifdef WITH_SSL -#define HTTPS_URL "https://" /* https URL prefix */ - -#define IS_HTTP_TYPE(urltype) \ - (((urltype) == HTTP_URL_T) || ((urltype) == HTTPS_URL_T)) -#else -#define IS_HTTP_TYPE(urltype) \ - ((urltype) == HTTP_URL_T) -#endif - -/* - * 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 preceded 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, *errormsg; - char *ep, *clear, *realm; - char uuser[BUFSIZ], *gotpass; - const char *upass; - int rval; - size_t len, clen, rlen; - - *response = NULL; - clear = realm = NULL; - rval = -1; - cp = challenge; - scheme = "Basic"; /* only support Basic authentication */ - gotpass = NULL; - - DPRINTF("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) { - len = ep - cp; - realm = (char *)ftp_malloc(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(uuser, guser, sizeof(uuser)); - fprintf(ttyout, "%s\n", uuser); - } else { - (void)fflush(ttyout); - if (get_line(stdin, uuser, sizeof(uuser), &errormsg) < 0) { - warnx("%s; can't authenticate", errormsg); - goto cleanup_auth_url; - } - } - if (gpass != NULL) - upass = gpass; - else { - gotpass = getpass("Password: "); - if (gotpass == NULL) { - warnx("Can't read password"); - goto cleanup_auth_url; - } - upass = gotpass; - } - - clen = strlen(uuser) + strlen(upass) + 2; /* user + ":" + pass + "\0" */ - clear = (char *)ftp_malloc(clen); - (void)strlcpy(clear, uuser, clen); - (void)strlcat(clear, ":", clen); - (void)strlcat(clear, upass, clen); - if (gotpass) - memset(gotpass, 0, strlen(gotpass)); - - /* scheme + " " + enc + "\0" */ - rlen = strlen(scheme) + 1 + (clen + 2) * 4 / 3 + 1; - *response = (char *)ftp_malloc(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; - size_t 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 (per RFC 3986): - * ://[[:]@][:][/] - * 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://. - * - * XXX: this is not totally RFC 3986 compliant; 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 - * --------- ----------- - * "http://host" "/" - * "http://host/" "/" - * "http://host/path" "/path" - * "file://host/dir/file" "dir/file" - * "ftp://host" "" - * "ftp://host/" "" - * "ftp://host//" "/" - * "ftp://host/dir/file" "dir/file" - * "ftp://host//dir/file" "/dir/file" - */ -static int -parse_url(const char *url, const char *desc, url_t *utype, - char **uuser, char **pass, char **host, char **port, - in_port_t *portnum, char **path) -{ - const char *origurl, *tport; - char *cp, *ep, *thost; - size_t len; - - if (url == NULL || desc == NULL || utype == NULL || uuser == NULL - || pass == NULL || host == NULL || port == NULL || portnum == NULL - || path == NULL) - errx(1, "parse_url: invoked with NULL argument!"); - DPRINTF("parse_url: %s `%s'\n", desc, url); - - origurl = url; - *utype = UNKNOWN_URL_T; - *uuser = *pass = *host = *port = *path = NULL; - *portnum = 0; - tport = NULL; - - if (STRNEQUAL(url, HTTP_URL)) { - url += sizeof(HTTP_URL) - 1; - *utype = HTTP_URL_T; - *portnum = HTTP_PORT; - tport = httpport; - } else if (STRNEQUAL(url, FTP_URL)) { - url += sizeof(FTP_URL) - 1; - *utype = FTP_URL_T; - *portnum = FTP_PORT; - tport = ftpport; - } else if (STRNEQUAL(url, FILE_URL)) { - url += sizeof(FILE_URL) - 1; - *utype = FILE_URL_T; -#ifdef WITH_SSL - } else if (STRNEQUAL(url, HTTPS_URL)) { - url += sizeof(HTTPS_URL) - 1; - *utype = HTTPS_URL_T; - *portnum = HTTPS_PORT; - tport = httpsport; -#endif - } else { - warnx("Invalid %s `%s'", desc, url); - cleanup_parse_url: - FREEPTR(*uuser); - if (*pass != NULL) - memset(*pass, 0, strlen(*pass)); - 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 = ftp_strdup(url); - else { - len = ep - url; - thost = (char *)ftp_malloc(len + 1); - (void)strlcpy(thost, url, len + 1); - if (*utype == FTP_URL_T) /* skip first / for ftp URLs */ - ep++; - *path = ftp_strdup(ep); - } - - cp = strchr(thost, '@'); /* look for user[:pass]@ in URLs */ - if (cp != NULL) { - if (*utype == FTP_URL_T) - anonftp = 0; /* disable anonftp */ - *uuser = thost; - *cp = '\0'; - thost = ftp_strdup(cp + 1); - cp = strchr(*uuser, ':'); - if (cp != NULL) { - *cp = '\0'; - *pass = ftp_strdup(cp + 1); - } - url_decode(*uuser); - if (*pass) - url_decode(*pass); - } - -#ifdef INET6 - /* - * Check if thost is an encoded IPv6 address, as per - * RFC 3986: - * `[' 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) { - unsigned long nport; - - nport = strtoul(cp, &ep, 10); - if (*cp == '\0' || *ep != '\0' || - nport < 1 || nport > MAX_IN_PORT_T) { - warnx("Unknown port `%s' in %s `%s'", - cp, desc, origurl); - goto cleanup_parse_url; - } - *portnum = nport; - tport = cp; - } - - if (tport != NULL) - *port = ftp_strdup(tport); - if (*path == NULL) { - const char *emptypath = "/"; - if (*utype == FTP_URL_T) /* skip first / for ftp URLs */ - emptypath++; - *path = ftp_strdup(emptypath); - } - - DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) " - "path `%s'\n", - STRorNULL(*uuser), STRorNULL(*pass), - STRorNULL(*host), STRorNULL(*port), - *portnum ? *portnum : -1, STRorNULL(*path)); - - 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/https_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; - sigfunc volatile oldint; - sigfunc volatile oldpipe; - sigfunc volatile oldalrm; - sigfunc volatile oldquit; - int volatile s; - struct stat sb; - int volatile ischunked; - int volatile isproxy; - int volatile rval; - int volatile hcode; - int len; - size_t flen; - static size_t bufsize; - static char *xferbuf; - const char *cp, *token; - char *ep; - char buf[FTPBUFLEN]; - const char *errormsg; - char *volatile savefile; - char *volatile auth; - char *volatile location; - char *volatile message; - char *uuser, *pass, *host, *port, *path; - char *volatile decodedpath; - char *puser, *ppass, *useragent; - off_t hashbytes, rangestart, rangeend, entitylen; - int (*volatile closefunc)(FILE *); - FETCH *volatile fin; - FILE *volatile fout; - const char *volatile penv = proxyenv; - time_t mtime; - url_t urltype; - in_port_t portnum; -#ifdef WITH_SSL - void *ssl; -#endif - - DPRINTF("%s: `%s' proxyenv `%s'\n", __func__, url, STRorNULL(penv)); - - oldquit = oldalrm = oldint = oldpipe = NULL; - closefunc = NULL; - fin = NULL; - fout = NULL; - s = -1; - savefile = NULL; - auth = location = message = NULL; - ischunked = isproxy = hcode = 0; - rval = 1; - uuser = pass = host = path = decodedpath = puser = ppass = NULL; - - if (sigsetjmp(httpabort, 1)) - goto cleanup_fetch_url; - - if (parse_url(url, "URL", &urltype, &uuser, &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 (!IS_HTTP_TYPE(urltype) || outfile == NULL) { - warnx("Invalid URL (no file after host) `%s'", url); - goto cleanup_fetch_url; - } - } - - decodedpath = ftp_strdup(path); - url_decode(decodedpath); - - if (outfile) - savefile = outfile; - else { - cp = strrchr(decodedpath, '/'); /* find savefile */ - if (cp != NULL) - savefile = ftp_strdup(cp + 1); - else - savefile = ftp_strdup(decodedpath); - } - DPRINTF("%s: savefile `%s'\n", __func__, savefile); - 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; - } - - restart_point = 0; - filesize = -1; - rangestart = rangeend = entitylen = -1; - mtime = -1; - if (restartautofetch) { - if (stat(savefile, &sb) == 0) - restart_point = sb.st_size; - } - if (urltype == FILE_URL_T) { /* file:// URLs */ - direction = "copied"; - fin = fetch_open(decodedpath, "r"); - if (fin == NULL) { - warn("Can't open `%s'", decodedpath); - goto cleanup_fetch_url; - } - if (fstat(fetch_fileno(fin), &sb) == 0) { - mtime = sb.st_mtime; - filesize = sb.st_size; - } - if (restart_point) { - if (lseek(fetch_fileno(fin), restart_point, SEEK_SET) < 0) { - warn("Can't seek 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); - } - if (0 == rcvbuf_size) { - rcvbuf_size = 8 * 1024; /* XXX */ - } - } else { /* ftp:// or http:// URLs */ - const char *leading; - int hasleading; - - if (penv == NULL) { -#ifdef WITH_SSL - if (urltype == HTTPS_URL_T) - penv = getoptionvalue("https_proxy"); -#endif - if (penv == NULL && IS_HTTP_TYPE(urltype)) - penv = getoptionvalue("http_proxy"); - else if (urltype == FTP_URL_T) - penv = getoptionvalue("ftp_proxy"); - } - direction = "retrieved"; - if (! EMPTYSTRING(penv)) { /* use proxy */ - url_t purltype; - char *phost, *ppath; - char *pport, *no_proxy; - in_port_t pportnum; - - isproxy = 1; - - /* check URL against list of no_proxied sites */ - no_proxy = getoptionvalue("no_proxy"); - if (! EMPTYSTRING(no_proxy)) { - char *np, *np_copy, *np_iter; - unsigned long np_port; - size_t hlen, plen; - - np_iter = np_copy = ftp_strdup(no_proxy); - hlen = strlen(host); - while ((cp = strsep(&np_iter, " ,")) != NULL) { - if (*cp == '\0') - continue; - if ((np = strrchr(cp, ':')) != NULL) { - *np++ = '\0'; - np_port = strtoul(np, &ep, 10); - if (*np == '\0' || *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 (restart_point) { - warnx("Can't restart via proxy URL `%s'", - penv); - goto cleanup_fetch_url; - } - if (parse_url(penv, "proxy URL", &purltype, - &puser, &ppass, &phost, &pport, &pportnum, - &ppath) == -1) - goto cleanup_fetch_url; - - if ((!IS_HTTP_TYPE(purltype) - && purltype != FTP_URL_T) || - EMPTYSTRING(phost) || - (! EMPTYSTRING(ppath) - && strcmp(ppath, "/") != 0)) { - warnx("Malformed proxy URL `%s'", penv); - 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 = ftp_strdup(url); - FREEPTR(ppath); - urltype = purltype; - } - } /* ! EMPTYSTRING(penv) */ - - 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, port, &hints, &res0); - if (error) { - warnx("Can't LOOKUP `%s:%s': %s", host, port, - (error == EAI_SYSTEM) ? strerror(errno) - : gai_strerror(error)); - goto cleanup_fetch_url; - } - if (res0->ai_canonname) - host = res0->ai_canonname; - - s = -1; -#ifdef WITH_SSL - ssl = NULL; -#endif - for (res = res0; res; res = res->ai_next) { - char hname[NI_MAXHOST], sname[NI_MAXSERV]; - - ai_unmapped(res); - if (getnameinfo(res->ai_addr, res->ai_addrlen, - hname, sizeof(hname), sname, sizeof(sname), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - strlcpy(hname, "?", sizeof(hname)); - strlcpy(sname, "?", sizeof(sname)); - } - - if (verbose && res0->ai_next) { - fprintf(ttyout, "Trying %s:%s ...\n", - hname, sname); - } - - s = socket(res->ai_family, SOCK_STREAM, - res->ai_protocol); - if (s < 0) { - warn( - "Can't create socket for connection to " - "`%s:%s'", hname, sname); - continue; - } - - if (ftp_connect(s, res->ai_addr, res->ai_addrlen, - verbose || !res->ai_next) < 0) { - close(s); - s = -1; - continue; - } - -#ifdef WITH_SSL - if (urltype == HTTPS_URL_T) { - if ((ssl = fetch_start_ssl(s)) == NULL) { - close(s); - s = -1; - continue; - } - } -#endif - - /* success */ - break; - } - - if (s < 0) { - warnx("Can't connect to `%s:%s'", host, port); - goto cleanup_fetch_url; - } - - oldalrm = xsignal(SIGALRM, timeouthttp); - alarmtimer(quit_time ? quit_time : 60); - fin = fetch_fdopen(s, "r+"); - fetch_set_ssl(fin, ssl); - alarmtimer(0); - - alarmtimer(quit_time ? quit_time : 60); - /* - * 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++; - } - fetch_printf(fin, "GET %s HTTP/1.0\r\n", path); - if (flushcache) - fetch_printf(fin, "Pragma: no-cache\r\n"); - } else { - fetch_printf(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 = ftp_strdup(host); - if (isipv6addr(h) && - (p = strchr(h, '%')) != NULL) { - *p = '\0'; - } - fetch_printf(fin, "Host: [%s]", h); - free(h); - } else - fetch_printf(fin, "Host: %s", host); -#ifdef WITH_SSL - if ((urltype == HTTP_URL_T && portnum != HTTP_PORT) || - (urltype == HTTPS_URL_T && portnum != HTTPS_PORT)) -#else - if (portnum != HTTP_PORT) -#endif - fetch_printf(fin, ":%u", portnum); - fetch_printf(fin, "\r\n"); - fetch_printf(fin, "Accept: */*\r\n"); - fetch_printf(fin, "Connection: close\r\n"); - if (restart_point) { - fputs(leading, ttyout); - fetch_printf(fin, "Range: bytes=" LLF "-\r\n", - (LLT)restart_point); - fprintf(ttyout, "restarting at " LLF, - (LLT)restart_point); - leading = ", "; - hasleading++; - } - if (flushcache) - fetch_printf(fin, "Cache-Control: no-cache\r\n"); - } - if ((useragent=getenv("FTPUSERAGENT")) != NULL) { - fetch_printf(fin, "User-Agent: %s\r\n", useragent); - } else { - fetch_printf(fin, "User-Agent: %s/%s\r\n", - FTP_PRODUCT, FTP_VERSION); - } - if (wwwauth) { - if (verbose) { - fprintf(ttyout, "%swith authorization", - leading); - leading = ", "; - hasleading++; - } - fetch_printf(fin, "Authorization: %s\r\n", wwwauth); - } - if (proxyauth) { - if (verbose) { - fprintf(ttyout, - "%swith proxy authorization", leading); - leading = ", "; - hasleading++; - } - fetch_printf(fin, "Proxy-Authorization: %s\r\n", proxyauth); - } - if (verbose && hasleading) - fputs(")\n", ttyout); - fetch_printf(fin, "\r\n"); - if (fetch_flush(fin) == EOF) { - warn("Writing HTTP request"); - alarmtimer(0); - goto cleanup_fetch_url; - } - alarmtimer(0); - - /* Read the response */ - alarmtimer(quit_time ? quit_time : 60); - len = fetch_getline(fin, buf, sizeof(buf), &errormsg); - alarmtimer(0); - if (len < 0) { - if (*errormsg == '\n') - errormsg++; - warnx("Receiving HTTP reply: %s", errormsg); - goto cleanup_fetch_url; - } - while (len > 0 && (ISLWS(buf[len-1]))) - buf[--len] = '\0'; - DPRINTF("%s: received `%s'\n", __func__, 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 = ftp_strdup(cp); - - /* Read the rest of the header. */ - while (1) { - alarmtimer(quit_time ? quit_time : 60); - len = fetch_getline(fin, buf, sizeof(buf), &errormsg); - alarmtimer(0); - if (len < 0) { - if (*errormsg == '\n') - errormsg++; - warnx("Receiving HTTP reply: %s", errormsg); - goto cleanup_fetch_url; - } - while (len > 0 && (ISLWS(buf[len-1]))) - buf[--len] = '\0'; - if (len == 0) - break; - DPRINTF("%s: received `%s'\n", __func__, 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; - DPRINTF("%s: parsed len as: " LLF "\n", - __func__, (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; - -#ifndef NO_DEBUG - if (ftp_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); - } -#endif - if (! restart_point) { - warnx( - "Received unexpected Content-Range header"); - goto cleanup_fetch_url; - } - - } else if (match_token(&cp, "Last-Modified:")) { - struct tm parsed; - const char *t; - - memset(&parsed, 0, sizeof(parsed)); - t = parse_rfc2616time(&parsed, cp); - if (t != NULL) { - parsed.tm_isdst = -1; - if (*t == '\0') - mtime = timegm(&parsed); -#ifndef NO_DEBUG - if (ftp_debug && mtime != -1) { - fprintf(ttyout, - "parsed time as: %s", - rfc2822time(localtime(&mtime))); - } -#endif - } - - } else if (match_token(&cp, "Location:")) { - location = ftp_strdup(cp); - DPRINTF("%s: parsed location as `%s'\n", - __func__, 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++; - DPRINTF("%s: using chunked encoding\n", - __func__); - - } else if (match_token(&cp, "Proxy-Authenticate:") - || match_token(&cp, "WWW-Authenticate:")) { - if (! (token = match_token(&cp, "Basic"))) { - DPRINTF("%s: skipping unknown auth " - "scheme `%s'\n", __func__, token); - continue; - } - FREEPTR(auth); - auth = ftp_strdup(token); - DPRINTF("%s: parsed auth as `%s'\n", - __func__, cp); - } - - } - /* finished parsing header */ - - 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: - case 307: - 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 = uuser; - 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 (get_line(stdin, reply, sizeof(reply), NULL) - < 0) { - 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, penv, - 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. */ - - /* - * Only trust filenames with special meaning if they came from - * the command line - */ - if (outfile == savefile) { - if (strcmp(savefile, "-") == 0) { - fout = stdout; - } else if (*savefile == '|') { - errx(1, "Piped output specifications are " - "not supported by tnftp: '%s'", - savefile); -#if 0 - oldpipe = xsignal(SIGPIPE, SIG_IGN); - fout = popen(savefile + 1, "w"); - if (fout == NULL) { - warn("Can't execute `%s'", savefile + 1); - goto cleanup_fetch_url; - } - closefunc = pclose; -#endif - } - } - if (fout == NULL) { - 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 */ - oldquit = xsignal(SIGQUIT, psummary); - oldint = xsignal(SIGINT, aborthttp); - - assert(rcvbuf_size > 0); - if ((size_t)rcvbuf_size > bufsize) { - if (xferbuf) - (void)free(xferbuf); - bufsize = rcvbuf_size; - xferbuf = ftp_malloc(bufsize); - } - - bytes = 0; - hashbytes = mark; - if (oldalrm) { - (void)xsignal(SIGALRM, oldalrm); - oldalrm = NULL; - } - progressmeter(-1); - - /* Finally, suck down the file. */ - do { - long chunksize; - short lastchunk; - - chunksize = 0; - lastchunk = 0; - /* read chunk-size */ - if (ischunked) { - if (fetch_getln(xferbuf, bufsize, fin) == NULL) { - warnx("Unexpected EOF reading chunk-size"); - goto cleanup_fetch_url; - } - errno = 0; - chunksize = strtol(xferbuf, &ep, 16); - if (ep == xferbuf) { - warnx("Invalid chunk-size"); - goto cleanup_fetch_url; - } - if (errno == ERANGE || chunksize < 0) { - errno = ERANGE; - warn("Chunk-size `%.*s'", - (int)(ep-xferbuf), xferbuf); - goto cleanup_fetch_url; - } - - /* - * XXX: Work around bug in Apache 1.3.9 and - * 1.3.11, which incorrectly put trailing - * space after the chunk-size. - */ - while (*ep == ' ') - ep++; - - /* skip [ chunk-ext ] */ - if (*ep == ';') { - while (*ep && *ep != '\r') - ep++; - } - - if (strcmp(ep, "\r\n") != 0) { - warnx("Unexpected data following chunk-size"); - goto cleanup_fetch_url; - } - DPRINTF("%s: got chunk-size of " LLF "\n", __func__, - (LLT)chunksize); - if (chunksize == 0) { - lastchunk = 1; - goto chunkdone; - } - } - /* transfer file or chunk */ - while (1) { - struct timeval then, now, td; - volatile off_t bufrem; - - if (rate_get) - (void)gettimeofday(&then, NULL); - bufrem = rate_get ? rate_get : (off_t)bufsize; - if (ischunked) - bufrem = MIN(chunksize, bufrem); - while (bufrem > 0) { - flen = fetch_read(xferbuf, sizeof(char), - MIN((off_t)bufsize, bufrem), fin); - if (flen <= 0) - goto chunkdone; - bytes += flen; - bufrem -= flen; - if (fwrite(xferbuf, sizeof(char), flen, fout) - != flen) { - 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 -= flen; - 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 (fetch_getln(xferbuf, bufsize, fin) == NULL) { - alarmtimer(0); - warnx("Unexpected EOF reading chunk CRLF"); - goto cleanup_fetch_url; - } - if (strcmp(xferbuf, "\r\n") != 0) { - warnx("Unexpected data following chunk"); - goto cleanup_fetch_url; - } - if (lastchunk) - break; - } - } while (ischunked); - -/* XXX: deal with optional trailer & CRLF here? */ - - if (hash && !progress && bytes > 0) { - if (bytes < mark) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - } - if (fetch_error(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", - rfc2822time(localtime(&mtime))); - } - } - if (bytes > 0) - ptransfer(0); - bytes = 0; - - rval = 0; - goto cleanup_fetch_url; - - improper: - warnx("Improper response from `%s:%s'", host, port); - - cleanup_fetch_url: - if (oldint) - (void)xsignal(SIGINT, oldint); - if (oldpipe) - (void)xsignal(SIGPIPE, oldpipe); - if (oldalrm) - (void)xsignal(SIGALRM, oldalrm); - if (oldquit) - (void)xsignal(SIGQUIT, oldpipe); - if (fin != NULL) - fetch_close(fin); - else if (s != -1) - close(s); - if (closefunc != NULL && fout != NULL) - (*closefunc)(fout); - if (res0) - freeaddrinfo(res0); - if (savefile != outfile) - FREEPTR(savefile); - FREEPTR(uuser); - if (pass != NULL) - memset(pass, 0, strlen(pass)); - FREEPTR(pass); - FREEPTR(host); - FREEPTR(port); - FREEPTR(path); - FREEPTR(decodedpath); - FREEPTR(puser); - if (ppass != NULL) - memset(ppass, 0, strlen(ppass)); - FREEPTR(ppass); - FREEPTR(auth); - FREEPTR(location); - FREEPTR(message); - return (rval); -} - -/* - * Abort a HTTP retrieval - */ -static void -aborthttp(int notused) -{ - char msgbuf[100]; - int len; - - sigint_raised = 1; - alarmtimer(0); - if (fromatty) { - len = snprintf(msgbuf, sizeof(msgbuf), - "\n%s: HTTP fetch aborted.\n", getprogname()); - if (len > 0) - write(fileno(ttyout), msgbuf, len); - } - siglongjmp(httpabort, 1); -} - -static void -timeouthttp(int notused) -{ - char msgbuf[100]; - int len; - - alarmtimer(0); - if (fromatty) { - len = snprintf(msgbuf, sizeof(msgbuf), - "\n%s: HTTP fetch timeout.\n", getprogname()); - if (len > 0) - 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, *uuser, *pass; - char *port; - char cmdbuf[MAXPATHLEN]; - char dirbuf[4]; - int dirhasglob, filehasglob, rval, transtype, xargc; - int oanonftp, oautologin; - in_port_t portnum; - url_t urltype; - - DPRINTF("fetch_ftp: `%s'\n", url); - host = path = dir = file = uuser = pass = NULL; - port = NULL; - rval = 1; - transtype = TYPE_I; - - if (STRNEQUAL(url, FTP_URL)) { - if ((parse_url(url, "URL", &urltype, &uuser, &pass, - &host, &port, &portnum, &path) == -1) || - (uuser != NULL && *uuser == '\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) - transtype = TYPE_A; - else if (strcasecmp(cp, ";type=i") == 0) - transtype = 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 = ftp_strdup(url); - cp = strchr(host, '@'); - if (cp != NULL) { - *cp = '\0'; - uuser = host; - anonftp = 0; /* disable anonftp */ - host = ftp_strdup(cp + 1); - } - cp = strchr(host, ':'); - if (cp != NULL) { - *cp = '\0'; - path = ftp_strdup(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; - (void)strlcpy(dirbuf, "/", sizeof(dirbuf)); - dir = dirbuf; - } 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) */ - } - DPRINTF("fetch_ftp: user `%s' pass `%s' host %s port %s " - "path `%s' dir `%s' file `%s'\n", - STRorNULL(uuser), STRorNULL(pass), - STRorNULL(host), STRorNULL(port), - STRorNULL(path), STRorNULL(dir), STRorNULL(file)); - - 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 */ - oanonftp = anonftp; - if (connected) - disconnect(0, NULL); - anonftp = oanonftp; - (void)strlcpy(cmdbuf, getprogname(), sizeof(cmdbuf)); - xargv[0] = cmdbuf; - 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, uuser, pass))) { - warnx("Can't connect or login to host `%s:%s'", - host, port ? port : "?"); - goto cleanup_fetch_ftp; - } - - switch (transtype) { - case TYPE_A: - setascii(1, xargv); - break; - case TYPE_I: - setbinary(1, xargv); - break; - default: - errx(1, "fetch_ftp: unknown transfer type %d", transtype); - } - - /* - * 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 3986 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 3986 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; - DPRINTF("fetch_ftp: dir `%s', nextpart `%s'\n", - STRorNULL(dir), STRorNULL(nextpart)); - if (urltype == FTP_URL_T || *dir != '\0') { - (void)strlcpy(cmdbuf, "cd", sizeof(cmdbuf)); - xargv[0] = cmdbuf; - 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 3986 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; - (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf)); - xargv[0] = cmdbuf; - xargv[1] = file; - xargv[2] = NULL; - if (dirhasglob || filehasglob) { - int ointeractive; - - ointeractive = interactive; - interactive = 0; - if (restartautofetch) - (void)strlcpy(cmdbuf, "mreget", sizeof(cmdbuf)); - else - (void)strlcpy(cmdbuf, "mget", sizeof(cmdbuf)); - xargv[0] = cmdbuf; - 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(port); - FREEPTR(host); - FREEPTR(path); - FREEPTR(uuser); - if (pass) - memset(pass, 0, strlen(pass)); - 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 *proxyenv; - char *p; - -#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 \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 .\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) -#ifdef WITH_SSL - || STRNEQUAL(url, HTTPS_URL) -#endif - || STRNEQUAL(url, FILE_URL)) - return (fetch_url(url, NULL, NULL, NULL)); - - /* - * If it contains "://" but does not begin with ftp:// - * or something that was already handled, then it's - * unsupported. - * - * If it contains ":" but not "://" then we assume the - * part before the colon is a host name, not an URL scheme, - * so we don't try to match that here. - */ - if ((p = strstr(url, "://")) != NULL && ! STRNEQUAL(url, FTP_URL)) - errx(1, "Unsupported URL scheme `%.*s'", (int)(p - url), url); - - /* - * Try FTP URL-style and host:file arguments next. - * If ftpproxy is set with an FTP URL, use fetch_url() - * Othewise, use fetch_ftp(). - */ - proxyenv = getoptionvalue("ftp_proxy"); - if (!EMPTYSTRING(proxyenv) && 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, rval; - - argpos = rval = 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) && (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); -} - - -/* - * Upload multiple files from the command line. - * - * If an error occurs the return value will be the offset+1 in - * argv[] of the file that caused a problem (i.e, argv[x] - * returns x+1) - * Otherwise, 0 is returned if all files uploaded successfully. - */ -int -auto_put(int argc, char **argv, const char *uploadserver) -{ - char *uargv[4], *path, *pathsep; - int uargc, rval, argpos; - size_t len; - char cmdbuf[MAX_C_NAME]; - - (void)strlcpy(cmdbuf, "mput", sizeof(cmdbuf)); - uargv[0] = cmdbuf; - uargv[1] = argv[0]; - uargc = 2; - uargv[2] = uargv[3] = NULL; - pathsep = NULL; - rval = 1; - - DPRINTF("auto_put: target `%s'\n", uploadserver); - - path = ftp_strdup(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 */ - len = strlen(uploadserver) + 2; /* path + "/" + "\0" */ - free(path); - path = (char *)ftp_malloc(len); - (void)strlcpy(path, uploadserver, len); - (void)strlcat(path, "/", len); - } else { /* single file to upload */ - (void)strlcpy(cmdbuf, "put", sizeof(cmdbuf)); - uargv[0] = cmdbuf; - pathsep = strrchr(path, '/'); - if (pathsep == NULL) { - pathsep = strrchr(path, ':'); - if (pathsep == NULL) { - warnx("Invalid URL `%s'", path); - goto cleanup_auto_put; - } - pathsep++; - uargv[2] = ftp_strdup(pathsep); - pathsep[0] = '/'; - } else - uargv[2] = ftp_strdup(pathsep + 1); - pathsep[1] = '\0'; - uargc++; - } - } - DPRINTF("auto_put: URL `%s' argv[2] `%s'\n", - path, STRorNULL(uargv[2])); - - /* connect and cwd */ - rval = auto_fetch(1, &path); - if(rval >= 0) - goto cleanup_auto_put; - - rval = 0; - - /* target filename provided; upload 1 file */ - /* XXX : is this the best way? */ - if (uargc == 3) { - uargv[1] = argv[0]; - put(uargc, uargv); - if ((code / 100) != COMPLETE) - rval = 1; - } else { /* otherwise a target dir: upload all files to it */ - for(argpos = 0; argv[argpos] != NULL; argpos++) { - uargv[1] = argv[argpos]; - mput(uargc, uargv); - if ((code / 100) != COMPLETE) { - rval = argpos + 1; - break; - } - } - } - - cleanup_auto_put: - free(path); - FREEPTR(uargv[2]); - return (rval); -} diff --git a/contrib/tnftp/ftp.1 b/contrib/tnftp/ftp.1 deleted file mode 100644 index 931f3b8ee8..0000000000 --- a/contrib/tnftp/ftp.1 +++ /dev/null @@ -1,2421 +0,0 @@ -.\" $NetBSD: ftp.1,v 1.134 2012/12/22 16:57:10 christos Exp $ -.\" -.\" Copyright (c) 1996-2010 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. -.\" -.\" 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 December 22, 2012 -.Dt FTP 1 -.Os -.Sh NAME -.Nm ftp -.Nd Internet file transfer program -.Sh SYNOPSIS -.Nm -.Op Fl 46AadefginpRtVv -.Op Fl N Ar netrc -.Op Fl o Ar output -.Op Fl P Ar port -.Op Fl q Ar quittime -.Op Fl r Ar retry -.Op Fl s Ar srcaddr -.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 Fl -.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 Ar netrc -Use -.Ar netrc -instead of -.Pa ~/.netrc . -Refer to -.Sx THE .netrc FILE -for more information. -.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 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 Ar port -Sets the port number to -.Ar port . -.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 q Ar quittime -Quit if the connection has stalled for -.Ar quittime -seconds. -.It Fl R -Restart all non-proxied auto-fetches. -.It Fl r Ar wait -Retry the connection attempt if it failed, pausing for -.Ar wait -seconds. -.It Fl s Ar srcaddr -Uses -.Ar srcaddr -as the local IP address for all connections. -.It Fl t -Enables packet tracing. -.It Fl T Ar direction Ns , Ns Ar maximum Ns Oo , Ns Ar increment Oc -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 -Disable -.Ic verbose -and -.Ic progress , -overriding the default of enabled when output is to a terminal. -.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. -.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 Ic -.It Ic \&! Op Ar command Op Ar args -Invoke an interactive shell on the local machine. -If there are arguments, the first is taken to be a command to execute -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 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 epsv epsv4 epsv6 -Toggle the use of the extended -.Dv EPSV -and -.Dv EPRT -commands on all IP, IPv4, and IPv6 connections respectively. -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 epsv , -.Ic epsv4 , -or -.Ic epsv6 -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 ftp_debug Op Ar ftp_debug-value -Toggle debugging mode. -If an optional -.Ar ftp_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 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 -.Pq Sq # -printing for each data block transferred. -The size of a data block defaults to 1024 bytes. -This can be changed by specifying -.Ar size -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. -Macro names can be a maximum of 8 characters. -Macros are only applicable to the current session they are -defined within (or if defined outside a session, to the session -invoked with the next -.Ic open -command), and remain defined until a -.Ic close -command is executed. -To invoke a macro, use the -.Ic $ -command (see above). -.Pp -The macro processor interprets -.Sq $ -and -.Sq \e -as special characters. -A -.Sq $ -followed by a number (or numbers) is replaced by the -corresponding argument on the macro invocation command line. -A -.Sq $ -followed by an -.Sq i -signals the macro processor that the executing macro is to be -looped. -On the first pass -.Dq $i -is replaced by the first argument on the macro invocation command -line, on the second pass it is replaced by the second argument, -and so on. -A -.Sq \e -followed by any character is replaced by that character. -Use the -.Sq \e -to prevent special treatment of the -.Sq $ . -.It Ic mdelete Op Ar remote-files -Delete the -.Ar remote-files -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, in -.Li RFC 2822 -format. -.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 -.Dq $1 , -.Dq $2 , -\&... -.Dq $9 -in -.Ar inpattern . -Use -.Sq \e -to prevent this special treatment of the -.Sq $ -character. -All other characters are treated literally, and are used to determine the -.Ic nmap -.Op Ar inpattern -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 -.Dq $1 , -.Dq $2 , -\&... -.Dq $9 -are replaced by any value resulting from the -.Ar inpattern -template. -The sequence -.Dq $0 -is replaced by the original filename. -Additionally, the sequence -.Dq 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: -.Dl nmap $1 sed "s/ *$//" \*[Gt] $1 -Use the -.Sq \e -character to prevent special treatment -of the -.Sq $ , -.Sq \&[ , -.Sq \&] , -and -.Sq \&, -characters. -.It Ic ntrans Op Ar inchars Op Ar outchars -Set or unset the filename character translation mechanism. -If no arguments are specified, the filename character -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 Ic rate Ar direction Oo Ar maximum Oo Ar increment Oc Oc -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: -.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 "https_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 https_proxy -Defaults to -.Ev $https_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 Ic user Ar user-name Oo Ar password Oo Ar account Oc Oc -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 -.Sq \&" -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 Oo Ar user Ns Li \&@ Oc Ns Ar host Ns Li \&: Ns Oo Ar path Oc \ -Ns Oo Li / Oc -.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 Li ftp:// Ns Oo Ar user Ns Oo Ns Li \&: Ns Ar password Oc Ns Li \&@ Oc \ -Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path Ns Oo Li / Oc \ -Ns Oo Li ;type= Ns Ar X Oc -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 3986 , -.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 3986 ) -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 Li http:// Ns Oo Ar user Ns Oo Li \&: Ns Ar password Oc Ns Li \&@ Oc \ -Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path -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. -.\" https://[user[:password]@]host[:port]/path -.It Li https:// Ns Oo Ar user Ns Oo Li \&: Ns Ar password Oc Ns Li \&@ Oc \ -Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path -An -.Tn HTTPS -URL, retrieved using the -.Tn HTTPS -protocol. -If -.Ic "set https_proxy" -is defined, it is used as a URL to an -.Tn HTTPS -proxy server. -If -.Tn HTTPS -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. -There is currently no certificate validation and verification. -.\" file:///path -.It Li file:/// Ns Ar path -A local URL, copied from -.Pa / Ns Ar path -on the local host. -.\" about: -.It Li about: Ns Ar topic -Display information regarding -.Ar topic ; -no file is retrieved for this auto-fetched element. -Supported values include: -.Bl -tag -width "about:version" -.It Li about:ftp -Information about -.Nm ftp . -.It Li about:version -The version of -.Nm ftp . -Useful to provide when reporting problems. -.El -.El -.Pp -Unless noted otherwise above, and -.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 -.Dq globbing -is enabled, local file names are expanded according to the rules -used in the -.Xr csh 1 ; -see 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. -Like the other tokens in the -.Pa .netrc -file, a -.Ic macdef -is applicable only to the -.Ic machine -definition preceding it. -A -.Ic macdef -entry cannot be used by multiple -.Ic machine -definitions; rather, it must be defined following each -.Ic machine -it is intended to be used with. -If a macro named -.Ic init -is defined, it is automatically executed as the last step in the -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 \&%c Ns Oo Oo Li 0 Oc Ns Ar n Oc , Ns Li \&%. Ns Oo Oo Li 0 Oc Ns Ar n Oc -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 -.\" ``/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 3986 -.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: -.Bl -tag -offset indent -width 8n -.It Li RFC 959 -.Em File Transfer Protocol -.It Li RFC 1123 -.Em Requirements for Internet Hosts - Application and Support -.It Li RFC 1635 -.Em How to Use Anonymous FTP -.It Li RFC 2389 -.Em Feature negotiation mechanism for the File Transfer Protocol -.It Li RFC 2428 -.Em FTP Extensions for IPv6 and NATs -.It Li RFC 2616 -.Em Hypertext Transfer Protocol -- HTTP/1.1 -.It Li RFC 2822 -.Em Internet Message Format -.It Li RFC 3659 -.Em Extensions to FTP -.It Li RFC 3986 -.Em Uniform Resource Identifier (URI) -.El -.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/ftp.c b/contrib/tnftp/ftp.c deleted file mode 100644 index d1a87859b5..0000000000 --- a/contrib/tnftp/ftp.c +++ /dev/null @@ -1,2153 +0,0 @@ -/* $NetBSD: ftp.c,v 1.164 2012/07/04 06:09:37 is Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; -#else -__RCSID("$NetBSD: ftp.c,v 1.164 2012/07/04 06:09:37 is Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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); -__dead static void abort_squared(int); - -struct sockinet { - union sockunion { - struct sockaddr_in su_sin; -#ifdef INET6 - struct sockaddr_in6 su_sin6; -#endif - } si_su; -#if !defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN) - int si_len; -#endif -}; - -#if !defined(HAVE_STRUCT_SOCKADDR_IN_SIN_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(const char *host, const char *port) -{ - int s = -1, error; - struct addrinfo hints, *res, *res0; - static char hostnamebuf[MAXHOSTNAMELEN]; - socklen_t len; - int on = 1; - - memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); - memset((char *)&myctladdr, 0, sizeof (myctladdr)); - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - error = getaddrinfo(host, port, &hints, &res0); - if (error) { - warnx("Can't lookup `%s:%s': %s", host, port, - (error == EAI_SYSTEM) ? strerror(errno) - : 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) { - char hname[NI_MAXHOST], sname[NI_MAXSERV]; - - ai_unmapped(res); - if (getnameinfo(res->ai_addr, res->ai_addrlen, - hname, sizeof(hname), sname, sizeof(sname), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - strlcpy(hname, "?", sizeof(hname)); - strlcpy(sname, "?", sizeof(sname)); - } - if (verbose && res0->ai_next) { - /* if we have multiple possibilities */ - fprintf(ttyout, "Trying %s:%s ...\n", hname, sname); - } - s = socket(res->ai_family, SOCK_STREAM, res->ai_protocol); - if (s < 0) { - warn("Can't create socket for connection to `%s:%s'", - hname, sname); - continue; - } - if (ftp_connect(s, res->ai_addr, res->ai_addrlen, - verbose || !res->ai_next) < 0) { - close(s); - s = -1; - continue; - } - - /* finally we got one */ - break; - } - if (s < 0) { - warnx("Can't connect to `%s:%s'", host, port); - 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("Can't determine my address of connection to `%s:%s'", - host, port); - 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) { - DWARN("setsockopt %s (ignored)", - "IPTOS_LOWDELAY"); - } - } -#endif - cin = fdopen(s, "r"); - cout = fdopen(s, "w"); - if (cin == NULL || cout == NULL) { - warnx("Can't fdopen socket"); - 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) { - DWARN("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; - -#ifndef NO_DEBUG - if (ftp_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); - } -#endif - 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); -} - -static const char *m421[] = { - "remote server timed out. Connection closed", - "user interrupt. Connection closed", - "remote server has closed connection", -}; - -int -getreply(int expecteof) -{ - char current_line[BUFSIZ]; /* last line of previous reply */ - int c, n, lineno; - 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 (lineno = 0 ;; lineno++) { - dig = n = code = 0; - cp = current_line; - while (alarmtimer(quit_time ? quit_time : 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) { - size_t midx; - if (reply_timeoutflag) - midx = 0; - else if (reply_abrtflag) - midx = 1; - else - midx = 2; - (void)fprintf(ttyout, - "421 Service not available, %s.\n", m421[midx]); - (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 (lineno == 0) - (void)strlcpy(reply_string, current_line, - sizeof(reply_string)); - if (lineno > 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 *ecin, FILE *din, int sec) -{ - int nr, nfd; - struct pollfd pfd[2]; - - nfd = 0; - if (ecin) { - pfd[nfd].fd = fileno(ecin); - pfd[nfd++].events = POLLIN; - } - - if (din) { - pfd[nfd].fd = fileno(din); - pfd[nfd++].events = POLLIN; - } - - if ((nr = ftp_poll(pfd, nfd, sec * 1000)) <= 0) - return nr; - - nr = 0; - nfd = 0; - if (ecin) - nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0; - if (din) - nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0; - return nr; -} - -sigjmp_buf xferabort; - -__dead static 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: 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); -} - -/* - * Read data from infd & write to outfd, using buf/bufsize as the temporary - * buffer, dealing with short writes. - * If rate_limit != 0, rate-limit the transfer. - * If hash_interval != 0, fputc('c', ttyout) every hash_interval bytes. - * Updates global variables: bytes. - * Returns 0 if ok, 1 if there was a read error, 2 if there was a write error. - * In the case of error, errno contains the appropriate error code. - */ -static int -copy_bytes(int infd, int outfd, char *buf, size_t bufsize, - int rate_limit, int hash_interval) -{ - volatile off_t hashc; - ssize_t inc, outc; - char *bufp; - struct timeval tvthen, tvnow, tvdiff; - off_t bufrem, bufchunk; - int serr; - - hashc = hash_interval; - if (rate_limit) - bufchunk = rate_limit; - else - bufchunk = bufsize; - - while (1) { - if (rate_limit) { - (void)gettimeofday(&tvthen, NULL); - } - errno = 0; - inc = outc = 0; - /* copy bufchunk at a time */ - bufrem = bufchunk; - while (bufrem > 0) { - inc = read(infd, buf, MIN((off_t)bufsize, bufrem)); - if (inc <= 0) - goto copy_done; - bytes += inc; - bufrem -= inc; - bufp = buf; - while (inc > 0) { - outc = write(outfd, bufp, inc); - if (outc < 0) - goto copy_done; - inc -= outc; - bufp += outc; - } - if (hash_interval) { - while (bytes >= hashc) { - (void)putc('#', ttyout); - hashc += hash_interval; - } - (void)fflush(ttyout); - } - } - if (rate_limit) { /* rate limited; wait if necessary */ - while (1) { - (void)gettimeofday(&tvnow, NULL); - timersub(&tvnow, &tvthen, &tvdiff); - if (tvdiff.tv_sec > 0) - break; - usleep(1000000 - tvdiff.tv_usec); - } - } - } - - copy_done: - serr = errno; - if (hash_interval && bytes > 0) { - if (bytes < hash_interval) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - (void)fflush(ttyout); - } - errno = serr; - if (inc == -1) - return 1; - if (outc == -1) - return 2; - - return 0; -} - -void -sendrequest(const char *cmd, const char *local, const char *remote, - int printnames) -{ - struct stat st; - int c; - FILE *volatile fin; - FILE *volatile dout; - int (*volatile closefunc)(FILE *); - sigfunc volatile oldintr; - sigfunc volatile oldintp; - off_t volatile hashbytes; - int hash_interval; - const char *lmode; - static size_t bufsize; - static char *buf; - int oprogress; - - hashbytes = mark; - direction = "sent"; - dout = NULL; - bytes = 0; - filesize = -1; - oprogress = progress; - if (verbose && printnames) { - if (*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("Can't execute `%s'", local + 1); - code = -1; - goto cleanupsend; - } - progress = 0; - closefunc = pclose; - } else { - fin = fopen(local, "r"); - if (fin == NULL) { - warn("Can't open `%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("Can't seek to restart `%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; - - assert(sndbuf_size > 0); - if ((size_t)sndbuf_size > bufsize) { - if (buf) - (void)free(buf); - bufsize = sndbuf_size; - buf = ftp_malloc(bufsize); - } - - progressmeter(-1); - oldintp = xsignal(SIGPIPE, SIG_IGN); - hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0; - - switch (curtype) { - - case TYPE_I: - case TYPE_L: - c = copy_bytes(fileno(fin), fileno(dout), buf, bufsize, - rate_put, hash_interval); - if (c == 1) { - warn("Reading `%s'", local); - } else if (c == 2) { - if (errno != EPIPE) - warn("Writing to network"); - bytes = -1; - } - break; - - case TYPE_A: - while ((c = getc(fin)) != EOF) { - if (c == '\n') { - while (hash_interval && 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 959 */ - if (c == '\r') { - (void)putc('\0', dout); - bytes++; - } -#endif - } - if (hash_interval) { - if (bytes < hashbytes) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - } - if (ferror(fin)) - warn("Reading `%s'", local); - if (ferror(dout)) { - if (errno != EPIPE) - warn("Writing to network"); - 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 *volatile local, const char *remote, - const char *lmode, int printnames, int ignorespecial) -{ - FILE *volatile fout; - FILE *volatile din; - int (*volatile closefunc)(FILE *); - sigfunc volatile oldintr; - sigfunc volatile oldintp; - int c, d; - int volatile is_retr; - int volatile tcrflag; - int volatile bare_lfs; - static size_t bufsize; - static char *buf; - off_t volatile hashbytes; - int hash_interval; - struct stat st; - time_t mtime; - struct timeval tval[2]; - int oprogress; - int opreserve; - - 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 (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("Can't access `%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("Can't access `%s'", local); - code = -1; - goto cleanuprecv; - } - if (!runique && errno == EACCES && - chmod(local, (S_IRUSR|S_IWUSR)) < 0) { - warn("Can't chmod `%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("Can't execute `%s'", local+1); - goto abort; - } - progress = 0; - preserve = 0; - closefunc = pclose; - } else { - fout = fopen(local, lmode); - if (fout == NULL) { - warn("Can't open `%s'", local); - goto abort; - } - closefunc = fclose; - } - - if (fstat(fileno(fout), &st) != -1 && !S_ISREG(st.st_mode)) { - progress = 0; - preserve = 0; - } - assert(rcvbuf_size > 0); - if ((size_t)rcvbuf_size > bufsize) { - if (buf) - (void)free(buf); - bufsize = rcvbuf_size; - buf = ftp_malloc(bufsize); - } - - progressmeter(-1); - hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0; - - switch (curtype) { - - case TYPE_I: - case TYPE_L: - if (is_retr && restart_point && - lseek(fileno(fout), restart_point, SEEK_SET) < 0) { - warn("Can't seek to restart `%s'", local); - goto cleanuprecv; - } - c = copy_bytes(fileno(din), fileno(fout), buf, bufsize, - rate_get, hash_interval); - if (c == 1) { - if (errno != EPIPE) - warn("Reading from network"); - bytes = -1; - } else if (c == 2) { - warn("Writing `%s'", 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("Can't seek to restart `%s'", local); - goto cleanuprecv; - } - } - while ((c = getc(din)) != EOF) { - if (c == '\n') - bare_lfs++; - while (c == '\r') { - while (hash_interval && 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_interval) { - if (bytes < hashbytes) - (void)putc('#', ttyout); - (void)putc('\n', ttyout); - } - if (ferror(din)) { - if (errno != EPIPE) - warn("Reading from network"); - bytes = -1; - } - if (ferror(fout)) - warn("Writing `%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, - rfc2822time(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; - unsigned int addr[16], port[2]; - unsigned int af, hal, pal; - socklen_t len; - const char *pasvcmd = NULL; - int overbose; - -#ifdef INET6 -#ifndef NO_DEBUG - if (myctladdr.su_family == AF_INET6 && ftp_debug && - (IN6_IS_ADDR_LINKLOCAL(&myctladdr.si_su.su_sin6.sin6_addr) || - IN6_IS_ADDR_SITELOCAL(&myctladdr.si_su.su_sin6.sin6_addr))) { - warnx("Use of scoped addresses can be troublesome"); - } -#endif -#endif - - reinit: - if (passivemode) { - data_addr = myctladdr; - data = socket(data_addr.su_family, SOCK_STREAM, 0); - if (data < 0) { - warn("Can't create socket for data connection"); - return (1); - } - if ((options & SO_DEBUG) && - setsockopt(data, SOL_SOCKET, SO_DEBUG, - (void *)&on, sizeof(on)) == -1) { - DWARN("setsockopt %s (ignored)", "SO_DEBUG"); - } - result = COMPLETE + 1; - switch (data_addr.su_family) { - case AF_INET: - if (epsv4 && !epsv4bad) { - pasvcmd = "EPSV"; - overbose = verbose; - if (ftp_debug == 0) - verbose = -1; - result = command("EPSV"); - verbose = overbose; - if (verbose > 0 && - (result == COMPLETE || !connected)) - fprintf(ttyout, "%s\n", reply_string); - if (!connected) - return (1); - /* - * 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; - DPRINTF("disabling epsv4 for this " - "connection\n"); - } - } - if (result != COMPLETE) { - pasvcmd = "PASV"; - result = command("PASV"); - if (!connected) - return (1); - } - break; -#ifdef INET6 - case AF_INET6: - if (epsv6 && !epsv6bad) { - pasvcmd = "EPSV"; - overbose = verbose; - if (ftp_debug == 0) - verbose = -1; - result = command("EPSV"); - verbose = overbose; - if (verbose > 0 && - (result == COMPLETE || !connected)) - fprintf(ttyout, "%s\n", reply_string); - if (!connected) - return (1); - /* - * this code is to be friendly with - * broken BSDI ftpd - */ - if (code / 10 == 22 && code != 229) { - fputs( - "wrong server: return code must be 229\n", - ttyout); - result = COMPLETE + 1; - } - if (result != COMPLETE) { - epsv6bad = 1; - DPRINTF("disabling epsv6 for this " - "connection\n"); - } - } - 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); - { - size_t 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; - - if (ftp_connect(data, (struct sockaddr *)&data_addr.si_su, - data_addr.su_len, 1) < 0) { - if (activefallback) { - (void)close(data); - data = -1; - passivemode = 0; -#if 0 - activefallback = 0; -#endif - goto reinit; - } - 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) { - DWARN("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("Can't create socket for data connection"); - if (tmpno) - sendport = 1; - return (1); - } - if (!sendport) - if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, - (void *)&on, sizeof(on)) == -1) { - warn("Can't set SO_REUSEADDR on data connection"); - goto bad; - } - if (bind(data, (struct sockaddr *)&data_addr.si_su, - data_addr.su_len) < 0) { - warn("Can't bind for data connection"); - goto bad; - } - if ((options & SO_DEBUG) && - setsockopt(data, SOL_SOCKET, SO_DEBUG, - (void *)&on, sizeof(on)) == -1) { - DWARN("setsockopt %s (ignored)", "SO_DEBUG"); - } - len = sizeof(data_addr.si_su); - memset((char *)&data_addr, 0, sizeof (data_addr)); - if (getsockname(data, (struct sockaddr *)&data_addr.si_su, &len) == -1) { - warn("Can't determine my address of data connection"); - goto bad; - } - data_addr.su_len = len; - if (ftp_listen(data, 1) < 0) - warn("Can't listen to data connection"); - - if (sendport) { - char hname[NI_MAXHOST], sname[NI_MAXSERV]; - struct sockinet tmp; - - switch (data_addr.su_family) { - case AF_INET: - if (!epsv4 || epsv4bad) { - result = COMPLETE + 1; - break; - } - /* FALLTHROUGH */ -#ifdef INET6 - case AF_INET6: - if (!epsv6 || epsv6bad) { - result = COMPLETE + 1; - break; - } -#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 { - overbose = verbose; - if (ftp_debug == 0) - verbose = -1; - result = command("EPRT |%u|%s|%s|", af, hname, - sname); - verbose = overbose; - if (verbose > 0 && - (result == COMPLETE || !connected)) - fprintf(ttyout, "%s\n", reply_string); - if (!connected) - return (1); - if (result != COMPLETE) { - epsv4bad = 1; - DPRINTF("disabling epsv4 for this " - "connection\n"); - } - } - 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: { - uint8_t ua[sizeof(data_addr.si_su.su_sin6.sin6_addr)]; - uint8_t up[sizeof(data_addr.su_port)]; - - memcpy(ua, &data_addr.si_su.su_sin6.sin6_addr, - sizeof(ua)); - memcpy(up, &data_addr.su_port, sizeof(up)); - - 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, - ua[0], ua[1], ua[2], ua[3], - ua[4], ua[5], ua[6], ua[7], - ua[8], ua[9], ua[10], ua[11], - ua[12], ua[13], ua[14], ua[15], - 2, - up[0], up[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) { - DWARN("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 = ftp_poll(pfd, 1, timeout); - } while (rv == -1 && errno == EINTR); /* loop until poll ! EINTR */ - if (rv == -1) { - warn("Can't poll waiting before accept"); - goto dataconn_failed; - } - if (rv == 0) { - warnx("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("Can't accept data connection"); - 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) { - DWARN("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); - } -} - -__dead static 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 volatile oldintr; - int prox_type, nfnd; - int volatile secndflag; - const char *volatile cmd2; - - 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("Error aborting proxy command"); - 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) { - UPRINTF("usage: %s\n", argv[0]); - code = -1; - return; - } - while (nfnd > 0) { - if ((nfnd = empty(cin, NULL, 0)) < 0) { - warn("Error resetting connection"); - 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("Can't access `%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. - */ -static 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("Can't send abort message"); - fprintf(cout, "%cABOR\r\n", DM); - (void)fflush(cout); - if ((nfnd = empty(cin, din, 10)) <= 0) { - if (nfnd < 0) - warn("Can't send abort message"); - 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); -} - -/* - * Ensure that ai->ai_addr is NOT an IPv4 mapped address. - * IPv4 mapped address complicates too many things in FTP - * protocol handling, as FTP protocol is defined differently - * between IPv4 and IPv6. - * - * This may not be the best way to handle this situation, - * since the semantics of IPv4 mapped address is defined in - * the kernel. There are configurations where we should use - * IPv4 mapped address as native IPv6 address, not as - * "an IPv6 address that embeds IPv4 address" (namely, SIIT). - * - * More complete solution would be to have an additional - * getsockopt to grab "real" peername/sockname. "real" - * peername/sockname will be AF_INET if IPv4 mapped address - * is used to embed IPv4 address, and will be AF_INET6 if - * we use it as native. What a mess! - */ -void -ai_unmapped(struct addrinfo *ai) -{ -#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 defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN) - sin.sin_len = len; -#endif - memcpy(ai->ai_addr, &sin, len); - ai->ai_addrlen = len; -#endif -} - -#ifdef NO_USAGE -void -xusage(void) -{ - fputs("Usage error\n", ttyout); -} -#endif diff --git a/contrib/tnftp/ftp_var.h b/contrib/tnftp/ftp_var.h deleted file mode 100644 index 3548029d69..0000000000 --- a/contrib/tnftp/ftp_var.h +++ /dev/null @@ -1,355 +0,0 @@ -/* $NetBSD: ftp_var.h,v 1.82 2012/12/21 18:07:36 christos Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#include - -#include -#include - -#include - -#include -#include - -#ifndef NO_EDITCOMPLETE -#include -#endif /* !NO_EDITCOMPLETE */ - -#include "extern.h" -#include "progressbar.h" - -/* - * Format of command table. - */ -struct cmd { - const char *c_name; /* name of command */ - const char *c_help; /* help string */ - char c_bell; /* give bell when command completes */ - char c_conn; /* must be connected to use command */ - char c_proxy; /* proxy server may execute */ -#ifndef NO_EDITCOMPLETE - const char *c_complete; /* context sensitive completion list */ -#endif /* !NO_EDITCOMPLETE */ - void (*c_handler)(int, char **); /* function to call */ -}; - -#define MAX_C_NAME 12 /* maximum length of cmd.c_name */ - -/* - * 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 { - const 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") */ -#define HTTPS_PORT 443 /* default if ! getservbyname("https/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 ftp_debug; /* debugging level */ -GLOBAL int bell; /* ring bell on cmd completion */ -GLOBAL int doglob; /* glob local file names */ -GLOBAL int autologin; /* establish user account on connection */ -GLOBAL int proxy; /* proxy server connection active */ -GLOBAL int proxflag; /* proxy connection exists */ -GLOBAL int gatemode; /* use gate-ftp */ -GLOBAL const 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 const 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 epsv6; /* use EPSV/EPRT on IPv6 connections */ -GLOBAL int epsv6bad; /* 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 *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 const char *ftpport; /* port number to use for FTP connections */ -GLOBAL const char *httpport; /* port number to use for HTTP connections */ -#ifdef WITH_SSL -GLOBAL const char *httpsport; /* port number to use for HTTPS connections */ -#endif -GLOBAL const char *gateport; /* port number to use for gateftp connections */ -GLOBAL struct addrinfo *bindai; /* local address to bind as */ - -GLOBAL char *outfile; /* filename to output URLs to */ -GLOBAL int restartautofetch; /* restart auto-fetch */ - -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_STRUCT_SOCKADDR_IN_SIN_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 - -#ifdef NO_DEBUG -#define DPRINTF(...) -#define DWARN(...) -#else -#define DPRINTF(...) if (ftp_debug) (void)fprintf(ttyout, __VA_ARGS__) -#define DWARN(...) if (ftp_debug) warn(__VA_ARGS__) -#endif - -#define STRorNULL(s) ((s) ? (s) : "") - -#ifdef NO_USAGE -void xusage(void); -#define UPRINTF(...) xusage() -#else -#define UPRINTF(...) (void)fprintf(ttyout, __VA_ARGS__) -#endif diff --git a/contrib/tnftp/main.c b/contrib/tnftp/main.c deleted file mode 100644 index c84364d58d..0000000000 --- a/contrib/tnftp/main.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* $NetBSD: main.c,v 1.122 2012/12/22 16:57:10 christos Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved.\ - Copyright 1996-2008 The NetBSD Foundation, Inc. All rights reserved"); -#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.122 2012/12/22 16:57:10 christos Exp $"); -#endif -#endif /* not lint */ - -/* - * FTP User Program -- Command Interface. - */ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 HTTPS_PROXY "https_proxy" /* env var with HTTPS proxy location */ -#define NO_PROXY "no_proxy" /* env var with list of non-proxied - * hosts, comma or space separated */ - -__dead static void usage(void); -static void setupoption(const char *, const char *, const char *); - -int -main(int volatile argc, char **volatile argv) -{ - int ch, rval; - struct passwd *pw; - char *cp, *ep, *anonpass, *upload_path, *src_addr; - const char *anonuser; - int dumbterm, isupload; - size_t len; - - tzset(); - setlocale(LC_ALL, ""); - setprogname(argv[0]); - - sigint_raised = 0; - - ftpport = "ftp"; - httpport = "http"; -#ifdef WITH_SSL - httpsport = "https"; -#endif - 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; - epsv6 = 1; -#else - epsv4 = 0; - epsv6 = 0; -#endif - epsv4bad = 0; - epsv6bad = 0; - src_addr = NULL; - upload_path = NULL; - isupload = 0; - reply_callback = NULL; -#ifdef INET6 - family = AF_UNSPEC; -#else - family = AF_INET; /* force AF_INET if no INET6 support */ -#endif - - netrc[0] = '\0'; - cp = getenv("NETRC"); - if (cp != NULL && strlcpy(netrc, cp, sizeof(netrc)) >= sizeof(netrc)) - errx(1, "$NETRC `%s': %s", cp, strerror(ENAMETOOLONG)); - - marg_sl = ftp_sl_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:Rs:tT: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; - ftp_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 's': - src_addr = optarg; - break; - - case 't': - trace = 1; - break; - - case 'T': - { - int targc; - char *targv[6], *oac; - char cmdbuf[MAX_C_NAME]; - - /* look for `dir,max[,incr]' */ - targc = 0; - (void)strlcpy(cmdbuf, "-T", sizeof(cmdbuf)); - targv[targc++] = cmdbuf; - oac = ftp_strdup(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 = ftp_strdup(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 */ - - if (src_addr != NULL) { - struct addrinfo hints; - int error; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - error = getaddrinfo(src_addr, NULL, &hints, &bindai); - if (error) { - errx(1, "Can't lookup `%s': %s", src_addr, - (error == EAI_SYSTEM) ? strerror(errno) - : gai_strerror(error)); - } - } - - /* - * Cache the user name and home directory. - */ - localhome = NULL; - localname = NULL; - anonuser = "anonymous"; - cp = getenv("HOME"); - if (! EMPTYSTRING(cp)) - localhome = ftp_strdup(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 = ftp_strdup(pw->pw_dir); - localname = ftp_strdup(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 = ftp_strdup("/"); - - /* - * 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 = ftp_malloc(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("https_proxy", getenv(HTTPS_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); - - 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], *uuser, *host; - char cmdbuf[MAXPATHLEN]; - - if ((rval = sigsetjmp(toplevel, 1))) - goto sigint_or_rval_exit; - (void)xsignal(SIGINT, intr); - (void)xsignal(SIGPIPE, lostpeer); - uuser = NULL; - host = argv[0]; - cp = strchr(host, '@'); - if (cp) { - *cp = '\0'; - uuser = host; - host = cp + 1; - } - (void)strlcpy(cmdbuf, getprogname(), sizeof(cmdbuf)); - xargv[0] = cmdbuf; - xargv[1] = host; - xargv[2] = argv[1]; - xargv[3] = NULL; - do { - int oautologin; - - oautologin = autologin; - if (uuser != NULL) { - anonftp = 0; - autologin = 0; - } - setpeer(argc+1, xargv); - autologin = oautologin; - if (connected == 1 && uuser != NULL) - (void)ftp_login(host, uuser, 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 **promptopt; - static char buf[MAXPATHLEN]; - - if (promptopt == NULL) { - struct option *o; - - o = getoption("prompt"); - if (o == NULL) - errx(1, "prompt: no such option `prompt'"); - promptopt = &(o->value); - } - formatbuf(buf, sizeof(buf), *promptopt ? *promptopt : DEFAULTPROMPT); - return (buf); -} - -/* - * Generate an rprompt - */ -char * -rprompt(void) -{ - static char **rpromptopt; - static char buf[MAXPATHLEN]; - - if (rpromptopt == NULL) { - struct option *o; - - o = getoption("rprompt"); - if (o == NULL) - errx(1, "rprompt: no such option `rprompt'"); - rpromptopt = &(o->value); - } - formatbuf(buf, sizeof(buf), *rpromptopt ? *rpromptopt : DEFAULTRPROMPT); - return (buf); -} - -/* - * Command parser. - */ -void -cmdscanner(void) -{ - struct cmd *c; - char *p; -#ifndef NO_EDITCOMPLETE - int ch; - size_t num; -#endif - int len; - char cmdbuf[MAX_C_NAME]; - - 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); - len = get_line(stdin, line, sizeof(line), NULL); - switch (len) { - case -1: /* EOF */ - case -2: /* error */ - if (fromatty) - putc('\n', ttyout); - quit(0, NULL); - /* NOTREACHED */ - case -3: /* too long; try again */ - fputs("Sorry, input line is too long.\n", - ttyout); - continue; - case 0: /* empty; try again */ - continue; - default: /* all ok */ - break; - } -#ifndef NO_EDITCOMPLETE - } else { - const char *buf; - HistEvent ev; - cursor_pos = NULL; - - buf = el_gets(el, &ch); - num = ch; - 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, (void *)margv) != 0) -#endif /* !NO_EDITCOMPLETE */ - fputs("?Invalid command.\n", ttyout); - continue; - } - if (c->c_conn && !connected) { - fputs("Not connected.\n", ttyout); - continue; - } - confirmrest = 0; - (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf)); - margv[0] = cmdbuf; - (*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(); - ftp_sl_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) -{ - static char bangstr[2] = { '!', '\0' }; - static char dollarstr[2] = { '$', '\0' }; - 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 == '!') ? bangstr : dollarstr); - /* 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], *cmd; - const char *p; - int isusage; - - cmd = argv[0]; - isusage = (strcmp(cmd, "usage") == 0); - if (argc == 0 || (isusage && argc == 1)) { - UPRINTF("usage: %s [command [...]]\n", cmd); - return; - } - if (argc == 1) { - StringList *buf; - - buf = ftp_sl_init(); - fprintf(ttyout, - "%sommands may be abbreviated. Commands are:\n\n", - proxy ? "Proxy c" : "C"); - for (c = cmdtab; (p = c->c_name) != NULL; c++) - if (!proxy || c->c_proxy) - ftp_sl_add(buf, ftp_strdup(p)); - list_vertical(buf); - sl_free(buf, 1); - return; - } - -#define HELPINDENT ((int) sizeof("disconnect")) - - while (--argc > 0) { - char *arg; - char cmdbuf[MAX_C_NAME]; - - 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) { - (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf)); - nargv[0] = cmdbuf; - (*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(const char *name, const char *value, const char *defaultvalue) -{ - set_option(name, value ? value : defaultvalue, 0); -} - -void -usage(void) -{ - const char *progname = getprogname(); - - (void)fprintf(stderr, -"usage: %s [-46AadefginpRtVv] [-N netrc] [-o outfile] [-P port] [-q quittime]\n" -" [-r retry] [-s srcaddr] [-T dir,max[,inc]]\n" -" [[user@]host [port]] [host:path[/]] [file:///file]\n" -" [ftp://[user[:pass]@]host[:port]/path[/]]\n" -" [http://[user[:pass]@]host[:port]/path] [...]\n" -#ifdef WITH_SSL -" [https://[user[:pass]@]host[:port]/path] [...]\n" -#endif -" %s -u URL file [...]\n", progname, progname); - exit(1); -} diff --git a/contrib/tnftp/progressbar.c b/contrib/tnftp/progressbar.c deleted file mode 100644 index 2350776d6b..0000000000 --- a/contrib/tnftp/progressbar.c +++ /dev/null @@ -1,472 +0,0 @@ -/* $NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp $ */ - -/*- - * Copyright (c) 1997-2009 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. - * - * 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 -#ifndef lint -__RCSID("$NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp $"); -#endif /* not lint */ - -/* - * FTP User Program -- Misc support routines - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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) */ - - -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 suffixes, per IEC 60027-2. - */ -static const char * const suffixes[] = { - "", /* 2^0 (byte) */ - "KiB", /* 2^10 Kibibyte */ - "MiB", /* 2^20 Mebibyte */ - "GiB", /* 2^30 Gibibyte */ - "TiB", /* 2^40 Tebibyte */ - "PiB", /* 2^50 Pebibyte */ - "EiB", /* 2^60 Exbibyte */ -#if 0 - /* The following are not necessary for signed 64-bit off_t */ - "ZiB", /* 2^70 Zebibyte */ - "YiB", /* 2^80 Yobibyte */ -#endif -}; -#define NSUFFIXES (int)(sizeof(suffixes) / sizeof(suffixes[0])) - -/* - * 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, i, remaining, barlength; - - /* - * 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 - size_t len; - char buf[256]; /* workspace for progress bar */ -#ifndef NO_PROGRESS -#define BAROVERHEAD 45 /* 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); - alarmtimer(0); - (void)xsignal(SIGALRM, SIG_DFL); - 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) { - alarmtimer(0); - (void)xsignal(SIGALRM, SIG_DFL); - } - } -#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((int)(sizeof(buf) - 1), ttywidth) - BAROVERHEAD; - if (prefix) - barlength -= (int)strlen(prefix); - if (barlength > 0) { - i = barlength * ratio / 100; - len += snprintf(buf + len, BUFLEFT, - "|%.*s%*s|", i, stars, (int)(barlength - i), ""); - } - } - - abbrevsize = cursize; - for (i = 0; abbrevsize >= 100000 && i < NSUFFIXES; i++) - abbrevsize >>= 10; - if (i == NSUFFIXES) - i--; - len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %-3s ", - (LLT)abbrevsize, - suffixes[i]); - - 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 < NSUFFIXES; i++) - bytespersec >>= 10; - len += snprintf(buf + len, BUFLEFT, - " " LLFP("3") ".%02d %.2sB/s ", - (LLT)(bytespersec / 1024), - (int)((bytespersec % 1024) * 100 / 1024), - suffixes[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; - size_t 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 < NSUFFIXES; i++) - bytespersec >>= 10; - if (i == NSUFFIXES) - i--; - len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %.2sB/s)", - (LLT)(bytespersec / 1024), - (int)((bytespersec % 1024) * 100 / 1024), - suffixes[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/progressbar.h b/contrib/tnftp/progressbar.h deleted file mode 100644 index f627e88d5f..0000000000 --- a/contrib/tnftp/progressbar.h +++ /dev/null @@ -1,92 +0,0 @@ -/* $NetBSD: progressbar.h,v 1.8 2009/04/12 10:18:52 lukem Exp $ */ - -/*- - * Copyright (c) 1996-2009 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. - * - * 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 -#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 const 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/ruserpass.c b/contrib/tnftp/ruserpass.c deleted file mode 100644 index e434052784..0000000000 --- a/contrib/tnftp/ruserpass.c +++ /dev/null @@ -1,318 +0,0 @@ -/* $NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem 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 -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95"; -#else -__RCSID("$NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#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 { - const 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, char **aname, char **apass, char **aacct) -{ - char *tmp; - const char *mydomain; - char myname[MAXHOSTNAMELEN + 1]; - 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("Can't read `%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()) > 0) switch(t) { - - case DEFAULT: - usedefault = 1; - /* FALL THROUGH */ - - case MACH: - if (!usedefault) { - if ((t = token()) == -1) - goto bad; - if (t != 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()) > 0 && - t != MACH && t != DEFAULT) switch(t) { - - case LOGIN: - if ((t = token()) == -1) - goto bad; - if (t) { - if (*aname == NULL) - *aname = ftp_strdup(tokval); - else { - if (strcmp(*aname, tokval)) - goto next; - } - } - break; - case PASSWD: - if ((*aname == NULL || strcmp(*aname, "anonymous")) && - fstat(fileno(cfile), &stb) >= 0 && - (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others"); - warnx("Remove password or make file unreadable by others"); - goto bad; - } - if ((t = token()) == -1) - goto bad; - if (t && *apass == NULL) - *apass = ftp_strdup(tokval); - break; - case ACCOUNT: - if (fstat(fileno(cfile), &stb) >= 0 - && (stb.st_mode & 077) != 0) { - warnx("Error: .netrc file is readable by others"); - warnx("Remove account or make file unreadable by others"); - goto bad; - } - if ((t = token()) == -1) - goto bad; - if (t && *aacct == NULL) - *aacct = ftp_strdup(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 == macros[macnum].mac_start) { - macros[macnum++].mac_end = tmp; - break; - } else 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: - if (t == -1) - goto bad; - (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 == '\\') - if ((c = getc(cfile)) == EOF) - break; - *cp++ = c; - if (cp == tokval + sizeof(tokval)) { - warnx("Token in .netrc too long"); - return (-1); - } - } - } else { - *cp++ = c; - while ((c = getc(cfile)) != EOF - && c != '\n' && c != '\t' && c != ' ' && c != ',') { - if (c == '\\') - if ((c = getc(cfile)) == EOF) - break; - *cp++ = c; - if (cp == tokval + sizeof(tokval)) { - warnx("Token in .netrc too long"); - return (-1); - } - } - } - *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/ssl.c b/contrib/tnftp/ssl.c deleted file mode 100644 index a33a2a1e0d..0000000000 --- a/contrib/tnftp/ssl.c +++ /dev/null @@ -1,609 +0,0 @@ -/* $NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp $ */ - -/*- - * Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav - * Copyright (c) 2008, 2010 Joerg Sonnenberger - * 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 - * in this position and unchanged. - * 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. 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. - * - * $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $ - */ - -#include -#ifndef lint -__RCSID("$NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp $"); -#endif - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "ssl.h" - -extern int quit_time, verbose, ftp_debug; -extern FILE *ttyout; - -struct fetch_connect { - int sd; /* file/socket descriptor */ - char *buf; /* buffer */ - size_t bufsize; /* buffer size */ - size_t bufpos; /* position of buffer */ - size_t buflen; /* length of buffer contents */ - struct { /* data cached after an - interrupted read */ - char *buf; - size_t size; - size_t pos; - size_t len; - } cache; - int issock; - int iserr; - int iseof; - SSL *ssl; /* SSL handle */ -}; - -/* - * Write a vector to a connection w/ timeout - * Note: can modify the iovec. - */ -static ssize_t -fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt) -{ - struct timeval now, timeout, delta; - fd_set writefds; - ssize_t len, total; - int r; - - if (quit_time > 0) { - FD_ZERO(&writefds); - gettimeofday(&timeout, NULL); - timeout.tv_sec += quit_time; - } - - total = 0; - while (iovcnt > 0) { - while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) { - FD_SET(conn->sd, &writefds); - gettimeofday(&now, NULL); - delta.tv_sec = timeout.tv_sec - now.tv_sec; - delta.tv_usec = timeout.tv_usec - now.tv_usec; - if (delta.tv_usec < 0) { - delta.tv_usec += 1000000; - delta.tv_sec--; - } - if (delta.tv_sec < 0) { - errno = ETIMEDOUT; - return -1; - } - errno = 0; - r = select(conn->sd + 1, NULL, &writefds, NULL, &delta); - if (r == -1) { - if (errno == EINTR) - continue; - return -1; - } - } - errno = 0; - if (conn->ssl != NULL) - len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len); - else - len = writev(conn->sd, iov, iovcnt); - if (len == 0) { - /* we consider a short write a failure */ - /* XXX perhaps we shouldn't in the SSL case */ - errno = EPIPE; - return -1; - } - if (len < 0) { - if (errno == EINTR) - continue; - return -1; - } - total += len; - while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) { - len -= iov->iov_len; - iov++; - iovcnt--; - } - if (iovcnt > 0) { - iov->iov_len -= len; - iov->iov_base = (char *)iov->iov_base + len; - } - } - return total; -} - -/* - * Write to a connection w/ timeout - */ -static int -fetch_write(struct fetch_connect *conn, const char *str, size_t len) -{ - struct iovec iov[1]; - - iov[0].iov_base = __DECONST(char *, str); - iov[0].iov_len = len; - return fetch_writev(conn, iov, 1); -} - -/* - * Send a formatted line; optionally echo to terminal - */ -int -fetch_printf(struct fetch_connect *conn, const char *fmt, ...) -{ - va_list ap; - size_t len; - char *msg; - int r; - - va_start(ap, fmt); - len = vasprintf(&msg, fmt, ap); - va_end(ap); - - if (msg == NULL) { - errno = ENOMEM; - return -1; - } - - r = fetch_write(conn, msg, len); - free(msg); - return r; -} - -int -fetch_fileno(struct fetch_connect *conn) -{ - - return conn->sd; -} - -int -fetch_error(struct fetch_connect *conn) -{ - - return conn->iserr; -} - -static void -fetch_clearerr(struct fetch_connect *conn) -{ - - conn->iserr = 0; -} - -int -fetch_flush(struct fetch_connect *conn) -{ - int v; - - if (conn->issock) { -#ifdef TCP_NOPUSH - v = 0; - setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v)); -#endif - v = 1; - setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v)); - } - return 0; -} - -/*ARGSUSED*/ -struct fetch_connect * -fetch_open(const char *fname, const char *fmode) -{ - struct fetch_connect *conn; - int fd; - - fd = open(fname, O_RDONLY); /* XXX: fmode */ - if (fd < 0) - return NULL; - - if ((conn = calloc(1, sizeof(*conn))) == NULL) { - close(fd); - return NULL; - } - - conn->sd = fd; - conn->issock = 0; - return conn; -} - -/*ARGSUSED*/ -struct fetch_connect * -fetch_fdopen(int sd, const char *fmode) -{ - struct fetch_connect *conn; -#if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH) - int opt = 1; -#endif - - if ((conn = calloc(1, sizeof(*conn))) == NULL) - return NULL; - - conn->sd = sd; - conn->issock = 1; - fcntl(sd, F_SETFD, FD_CLOEXEC); -#ifdef SO_NOSIGPIPE - setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); -#endif -#ifdef TCP_NOPUSH - setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt)); -#endif - return conn; -} - -int -fetch_close(struct fetch_connect *conn) -{ - int rv = 0; - - if (conn != NULL) { - fetch_flush(conn); - SSL_free(conn->ssl); - rv = close(conn->sd); - if (rv < 0) { - errno = rv; - rv = EOF; - } - free(conn->cache.buf); - free(conn->buf); - free(conn); - } - return rv; -} - -#define FETCH_READ_WAIT -2 -#define FETCH_READ_ERROR -1 - -static ssize_t -fetch_ssl_read(SSL *ssl, void *buf, size_t len) -{ - ssize_t rlen; - int ssl_err; - - rlen = SSL_read(ssl, buf, len); - if (rlen < 0) { - ssl_err = SSL_get_error(ssl, rlen); - if (ssl_err == SSL_ERROR_WANT_READ || - ssl_err == SSL_ERROR_WANT_WRITE) { - return FETCH_READ_WAIT; - } - ERR_print_errors_fp(ttyout); - return FETCH_READ_ERROR; - } - return rlen; -} - -static ssize_t -fetch_nonssl_read(int sd, void *buf, size_t len) -{ - ssize_t rlen; - - rlen = read(sd, buf, len); - if (rlen < 0) { - if (errno == EAGAIN || errno == EINTR) - return FETCH_READ_WAIT; - return FETCH_READ_ERROR; - } - return rlen; -} - -/* - * Cache some data that was read from a socket but cannot be immediately - * returned because of an interrupted system call. - */ -static int -fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes) -{ - - if (conn->cache.size < nbytes) { - char *tmp = realloc(conn->cache.buf, nbytes); - if (tmp == NULL) - return -1; - - conn->cache.buf = tmp; - conn->cache.size = nbytes; - } - - memcpy(conn->cache.buf, src, nbytes); - conn->cache.len = nbytes; - conn->cache.pos = 0; - return 0; -} - -ssize_t -fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn) -{ - struct timeval now, timeout, delta; - fd_set readfds; - ssize_t rlen, total; - size_t len; - char *start, *buf; - - if (quit_time > 0) { - gettimeofday(&timeout, NULL); - timeout.tv_sec += quit_time; - } - - total = 0; - start = buf = ptr; - len = size * nmemb; - - if (conn->cache.len > 0) { - /* - * The last invocation of fetch_read was interrupted by a - * signal after some data had been read from the socket. Copy - * the cached data into the supplied buffer before trying to - * read from the socket again. - */ - total = (conn->cache.len < len) ? conn->cache.len : len; - memcpy(buf, conn->cache.buf, total); - - conn->cache.len -= total; - conn->cache.pos += total; - len -= total; - buf += total; - } - - while (len > 0) { - /* - * The socket is non-blocking. Instead of the canonical - * select() -> read(), we do the following: - * - * 1) call read() or SSL_read(). - * 2) if an error occurred, return -1. - * 3) if we received data but we still expect more, - * update our counters and loop. - * 4) if read() or SSL_read() signaled EOF, return. - * 5) if we did not receive any data but we're not at EOF, - * call select(). - * - * In the SSL case, this is necessary because if we - * receive a close notification, we have to call - * SSL_read() one additional time after we've read - * everything we received. - * - * In the non-SSL case, it may improve performance (very - * slightly) when reading small amounts of data. - */ - if (conn->ssl != NULL) - rlen = fetch_ssl_read(conn->ssl, buf, len); - else - rlen = fetch_nonssl_read(conn->sd, buf, len); - if (rlen == 0) { - break; - } else if (rlen > 0) { - len -= rlen; - buf += rlen; - total += rlen; - continue; - } else if (rlen == FETCH_READ_ERROR) { - if (errno == EINTR) - fetch_cache_data(conn, start, total); - return -1; - } - FD_ZERO(&readfds); - while (!FD_ISSET(conn->sd, &readfds)) { - FD_SET(conn->sd, &readfds); - if (quit_time > 0) { - gettimeofday(&now, NULL); - if (!timercmp(&timeout, &now, >)) { - errno = ETIMEDOUT; - return -1; - } - timersub(&timeout, &now, &delta); - } - errno = 0; - if (select(conn->sd + 1, &readfds, NULL, NULL, - quit_time > 0 ? &delta : NULL) < 0) { - if (errno == EINTR) - continue; - return -1; - } - } - } - return total; -} - -#define MIN_BUF_SIZE 1024 - -/* - * Read a line of text from a connection w/ timeout - */ -char * -fetch_getln(char *str, int size, struct fetch_connect *conn) -{ - size_t tmpsize; - ssize_t len; - char c; - - if (conn->buf == NULL) { - if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) { - errno = ENOMEM; - conn->iserr = 1; - return NULL; - } - conn->bufsize = MIN_BUF_SIZE; - } - - if (conn->iserr || conn->iseof) - return NULL; - - if (conn->buflen - conn->bufpos > 0) - goto done; - - conn->buf[0] = '\0'; - conn->bufpos = 0; - conn->buflen = 0; - do { - len = fetch_read(&c, sizeof(c), 1, conn); - if (len == -1) { - conn->iserr = 1; - return NULL; - } - if (len == 0) { - conn->iseof = 1; - break; - } - conn->buf[conn->buflen++] = c; - if (conn->buflen == conn->bufsize) { - char *tmp = conn->buf; - tmpsize = conn->bufsize * 2 + 1; - if ((tmp = realloc(tmp, tmpsize)) == NULL) { - errno = ENOMEM; - conn->iserr = 1; - return NULL; - } - conn->buf = tmp; - conn->bufsize = tmpsize; - } - } while (c != '\n'); - - if (conn->buflen == 0) - return NULL; - done: - tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos)); - memcpy(str, conn->buf + conn->bufpos, tmpsize); - str[tmpsize] = '\0'; - conn->bufpos += tmpsize; - return str; -} - -int -fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen, - const char **errormsg) -{ - size_t len; - int rv; - - if (fetch_getln(buf, buflen, conn) == NULL) { - if (conn->iseof) { /* EOF */ - rv = -2; - if (errormsg) - *errormsg = "\nEOF received"; - } else { /* error */ - rv = -1; - if (errormsg) - *errormsg = "Error encountered"; - } - fetch_clearerr(conn); - return rv; - } - len = strlen(buf); - if (buf[len - 1] == '\n') { /* clear any trailing newline */ - buf[--len] = '\0'; - } else if (len == buflen - 1) { /* line too long */ - while (1) { - char c; - ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn); - if (rlen <= 0 || c == '\n') - break; - } - if (errormsg) - *errormsg = "Input line is too long"; - fetch_clearerr(conn); - return -3; - } - if (errormsg) - *errormsg = NULL; - return len; -} - -void * -fetch_start_ssl(int sock) -{ - SSL *ssl; - SSL_CTX *ctx; - int ret, ssl_err; - - /* Init the SSL library and context */ - if (!SSL_library_init()){ - fprintf(ttyout, "SSL library init failed\n"); - return NULL; - } - - SSL_load_error_strings(); - - ctx = SSL_CTX_new(SSLv23_client_method()); - SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); - - ssl = SSL_new(ctx); - if (ssl == NULL){ - fprintf(ttyout, "SSL context creation failed\n"); - SSL_CTX_free(ctx); - return NULL; - } - SSL_set_fd(ssl, sock); - while ((ret = SSL_connect(ssl)) == -1) { - ssl_err = SSL_get_error(ssl, ret); - if (ssl_err != SSL_ERROR_WANT_READ && - ssl_err != SSL_ERROR_WANT_WRITE) { - ERR_print_errors_fp(ttyout); - SSL_free(ssl); - return NULL; - } - } - - if (ftp_debug && verbose) { - X509 *cert; - X509_NAME *name; - char *str; - - fprintf(ttyout, "SSL connection established using %s\n", - SSL_get_cipher(ssl)); - cert = SSL_get_peer_certificate(ssl); - name = X509_get_subject_name(cert); - str = X509_NAME_oneline(name, 0, 0); - fprintf(ttyout, "Certificate subject: %s\n", str); - free(str); - name = X509_get_issuer_name(cert); - str = X509_NAME_oneline(name, 0, 0); - fprintf(ttyout, "Certificate issuer: %s\n", str); - free(str); - } - - return ssl; -} - - -void -fetch_set_ssl(struct fetch_connect *conn, void *ssl) -{ - conn->ssl = ssl; -} diff --git a/contrib/tnftp/ssl.h b/contrib/tnftp/ssl.h deleted file mode 100644 index e248bb29f2..0000000000 --- a/contrib/tnftp/ssl.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $NetBSD: ssl.h,v 1.2 2014/01/07 02:07:08 joerg Exp $ */ - -/*- - * Copyright (c) 2012 The NetBSD Foundation, Inc. - * 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. - * - * 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. - */ -#ifdef WITH_SSL - -#define FETCH struct fetch_connect -struct fetch_connect; - -int fetch_printf(struct fetch_connect *, const char *fmt, ...) - __printflike(2, 3); -int fetch_fileno(struct fetch_connect *); -int fetch_error(struct fetch_connect *); -int fetch_flush(struct fetch_connect *); -struct fetch_connect *fetch_open(const char *, const char *); -struct fetch_connect *fetch_fdopen(int, const char *); -int fetch_close(struct fetch_connect *); -ssize_t fetch_read(void *, size_t, size_t, struct fetch_connect *); -char *fetch_getln(char *, int, struct fetch_connect *); -int fetch_getline(struct fetch_connect *, char *, size_t, const char **); -void fetch_set_ssl(struct fetch_connect *, void *); -void *fetch_start_ssl(int); - -#else /* !WITH_SSL */ - -#define FETCH FILE - -#define fetch_printf fprintf -#define fetch_fileno fileno -#define fetch_error ferror -#define fetch_flush fflush -#define fetch_open fopen -#define fetch_fdopen fdopen -#define fetch_close fclose -#define fetch_read fread -#define fetch_getln fgets -#define fetch_getline get_line -#define fetch_set_ssl(a, b) - -#endif /* !WITH_SSL */ diff --git a/contrib/tnftp/util.c b/contrib/tnftp/util.c deleted file mode 100644 index 19edbe5d82..0000000000 --- a/contrib/tnftp/util.c +++ /dev/null @@ -1,1542 +0,0 @@ -/* $NetBSD: util.c,v 1.158 2013/02/19 23:29:15 dsl Exp $ */ - -/*- - * Copyright (c) 1997-2009 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. - * - * 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 -#ifndef lint -__RCSID("$NetBSD: util.c,v 1.158 2013/02/19 23:29:15 dsl Exp $"); -#endif /* not lint */ - -/* - * FTP User Program -- Misc support routines - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ftp_var.h" - -/* - * Connect to peer server and auto-login, if possible. - */ -void -setpeer(int argc, char *argv[]) -{ - char *host; - const 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: - UPRINTF("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, "main: gateserver not defined"); - 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 *fline) -{ - - /* - * work-around broken ProFTPd servers that can't - * even obey RFC 2389. - */ - while (*fline && isspace((int)*fline)) - fline++; - - if (strcasecmp(fline, "MDTM") == 0) - features[FEAT_MDTM] = 1; - else if (strncasecmp(fline, "MLST", sizeof("MLST") - 1) == 0) { - features[FEAT_MLST] = 1; - } else if (strcasecmp(fline, "REST STREAM") == 0) - features[FEAT_REST_STREAM] = 1; - else if (strcasecmp(fline, "SIZE") == 0) - features[FEAT_SIZE] = 1; - else if (strcasecmp(fline, "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 (ftp_debug == 0) - verbose = -1; - - /* determine remote system type */ - if (command("SYST") == COMPLETE) { - if (overbose) { - int os_len = strcspn(reply_string + 4, " \r\n\t"); - if (os_len > 1 && reply_string[4 + os_len - 1] == '.') - os_len--; - fprintf(ttyout, "Remote system type is %.*s.\n", - os_len, reply_string + 4); - } - /* - * Decide whether we should default to bninary. - * Traditionally checked for "215 UNIX Type: L8", but - * some printers report "Linux" ! so be more forgiving. - * In reality we probably almost never want text any more. - */ - if (!strncasecmp(reply_string + 4, "unix", 4) || - !strncasecmp(reply_string + 4, "linux", 5)) { - 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; -#ifndef NO_DEBUG - if (ftp_debug) { -#define DEBUG_FEAT(x) fprintf(ttyout, "features[" #x "] = %d\n", features[(x)]) - DEBUG_FEAT(FEAT_FEAT); - DEBUG_FEAT(FEAT_MDTM); - DEBUG_FEAT(FEAT_MLST); - DEBUG_FEAT(FEAT_REST_STREAM); - DEBUG_FEAT(FEAT_SIZE); - DEBUG_FEAT(FEAT_TVFS); -#undef DEBUG_FEAT - } -#endif - 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; - epsv6bad = 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 *luser, const char *lpass) -{ - char tmp[80]; - char *fuser, *pass, *facct, *p; - char emptypass[] = ""; - const char *errormsg; - int n, aflag, rval, nlen; - - aflag = rval = 0; - fuser = pass = facct = NULL; - if (luser) - fuser = ftp_strdup(luser); - if (lpass) - pass = ftp_strdup(lpass); - - DPRINTF("ftp_login: user `%s' pass `%s' host `%s'\n", - STRorNULL(fuser), STRorNULL(pass), STRorNULL(host)); - - /* - * Set up arguments for an anonymous FTP session, if necessary. - */ - if (anonftp) { - FREEPTR(fuser); - fuser = ftp_strdup("anonymous"); /* as per RFC 1635 */ - FREEPTR(pass); - pass = ftp_strdup(getoptionvalue("anonpass")); - } - - if (ruserpass(host, &fuser, &pass, &facct) < 0) { - code = -1; - goto cleanup_ftp_login; - } - - while (fuser == NULL) { - if (localname) - fprintf(ttyout, "Name (%s:%s): ", host, localname); - else - fprintf(ttyout, "Name (%s): ", host); - errormsg = NULL; - nlen = get_line(stdin, tmp, sizeof(tmp), &errormsg); - if (nlen < 0) { - fprintf(ttyout, "%s; %s aborted.\n", errormsg, "login"); - code = -1; - goto cleanup_ftp_login; - } else if (nlen == 0) { - fuser = ftp_strdup(localname); - } else { - fuser = ftp_strdup(tmp); - } - } - - if (gatemode) { - char *nuser; - size_t len; - - len = strlen(fuser) + 1 + strlen(host) + 1; - nuser = ftp_malloc(len); - (void)strlcpy(nuser, fuser, len); - (void)strlcat(nuser, "@", len); - (void)strlcat(nuser, host, len); - FREEPTR(fuser); - fuser = nuser; - } - - n = command("USER %s", fuser); - if (n == CONTINUE) { - if (pass == NULL) { - p = getpass("Password: "); - if (p == NULL) - p = emptypass; - pass = ftp_strdup(p); - memset(p, 0, strlen(p)); - } - n = command("PASS %s", pass); - memset(pass, 0, strlen(pass)); - } - if (n == CONTINUE) { - aflag++; - if (facct == NULL) { - p = getpass("Account: "); - if (p == NULL) - p = emptypass; - facct = ftp_strdup(p); - memset(p, 0, strlen(p)); - } - if (facct[0] == '\0') { - warnx("Login failed"); - goto cleanup_ftp_login; - } - n = command("ACCT %s", facct); - memset(facct, 0, strlen(facct)); - } - if ((n != COMPLETE) || - (!aflag && facct != NULL && command("ACCT %s", facct) != COMPLETE)) { - warnx("Login failed"); - goto cleanup_ftp_login; - } - rval = 1; - username = ftp_strdup(fuser); - 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: - FREEPTR(fuser); - if (pass != NULL) - memset(pass, 0, strlen(pass)); - FREEPTR(pass); - if (facct != NULL) - memset(facct, 0, strlen(facct)); - FREEPTR(facct); - 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 *aprompt) -{ - const char *errormsg; - int ret, nlen; - size_t len; - - len = strlen(line); - if (len >= sizeof(line) - 3) { - fputs("Sorry, arguments too long.\n", ttyout); - intr(0); - } - fprintf(ttyout, "(%s) ", aprompt); - line[len++] = ' '; - errormsg = NULL; - nlen = get_line(stdin, line + len, sizeof(line)-len, &errormsg); - if (nlen < 0) { - fprintf(ttyout, "%s; %s aborted.\n", errormsg, "operation"); - intr(0); - } - len += nlen; - 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, const char **errbuf) -{ - static char buf[MAXPATHLEN]; - static FILE *ftemp = NULL; - static char **args; - char temp[MAXPATHLEN]; - int oldverbose, oldhash, oldprogress, fd; - char *cp; - const char *rmode; - size_t len; - - 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 (rmode = "w"; *++argv != NULL; rmode = "a") - recvrequest("NLST", temp, *argv, rmode, 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) - warnx("Can't find list of remote files"); - else - *errbuf = - "Can't find list of remote files"; - 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 (ftp_strdup(pattern)); - - flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE; - memset(&gl, 0, sizeof(gl)); - if (glob(pattern, flags, NULL, &gl) || gl.gl_pathc == 0) { - warnx("Glob pattern `%s' not found", pattern); - globfree(&gl); - return (NULL); - } - p = ftp_strdup(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 (ftp_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 && ftp_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 (ftp_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; - - /* - * 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); - } - memset(&timebuf, 0, sizeof(timebuf)); - if (strlen(timestr) != 14 || - (strptime(timestr, "%Y%m%d%H%M%S", &timebuf) == NULL)) { - bad_parse_time: - fprintf(ttyout, "Can't parse time `%s'.\n", timestr); - goto cleanup_parse_time; - } - timebuf.tm_isdst = -1; - rtime = timegm(&timebuf); - if (rtime == -1) { - if (noisy || ftp_debug != 0) - goto bad_parse_time; - else - goto cleanup_parse_time; - } else { - DPRINTF("remotemodtime: parsed time `%s' as " LLF - ", %s", - timestr, (LLT)rtime, - rfc2822time(localtime(&rtime))); - } - } else { - if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1) - features[FEAT_MDTM] = 0; - if (noisy && ftp_debug == 0) { - fputs(reply_string, ttyout); - putc('\n', ttyout); - } - } - cleanup_parse_time: - verbose = overbose; - if (rtime == -1) - code = ocode; - return (rtime); -} - -/* - * Format tm in an RFC 2822 compatible manner, with a trailing \n. - * Returns a pointer to a static string containing the result. - */ -const char * -rfc2822time(const struct tm *tm) -{ - static char result[50]; - - if (strftime(result, sizeof(result), - "%a, %d %b %Y %H:%M:%S %z\n", tm) == 0) - errx(1, "Can't convert RFC 2822 time: buffer too small"); - return result; -} - -/* - * Parse HTTP-date as per RFC 2616. - * Return a pointer to the next character of the consumed date string, - * or NULL if failed. - */ -const char * -parse_rfc2616time(struct tm *parsed, const char *httpdate) -{ - const char *t; - const char *curlocale; - - /* The representation of %a depends on the current locale. */ - curlocale = setlocale(LC_TIME, NULL); - (void)setlocale(LC_TIME, "C"); - /* RFC 1123 */ - if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) || - /* RFC 850 */ - (t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) || - /* asctime */ - (t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed))) { - ; /* do nothing */ - } - (void)setlocale(LC_TIME, curlocale); - return t; -} - -/* - * Update global `localcwd', which contains the state of the local cwd - */ -void -updatelocalcwd(void) -{ - - if (getcwd(localcwd, sizeof(localcwd)) == NULL) - localcwd[0] = '\0'; - DPRINTF("updatelocalcwd: got `%s'\n", localcwd); -} - -/* - * Update global `remotecwd', which contains the state of the remote cwd - */ -void -updateremotecwd(void) -{ - int overbose, ocode; - size_t i; - char *cp; - - overbose = verbose; - ocode = code; - if (ftp_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'; - DPRINTF("updateremotecwd: got `%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 parentdirbuf[PATH_MAX+1], *parentdir; - char realdir[PATH_MAX+1]; - size_t dirlen; - - /* determine parent directory of file */ - (void)strlcpy(parentdirbuf, file, sizeof(parentdirbuf)); - parentdir = dirname(parentdirbuf); - if (strcmp(parentdir, ".") == 0) - return 1; /* current directory is ok */ - - /* find the directory */ - if (realpath(parentdir, realdir) == NULL) { - warn("Unable to determine real path of `%s'", parentdir); - return 0; - } - if (realdir[0] != '/') /* relative result is ok */ - return 1; - dirlen = strlen(dir); - if (strncmp(realdir, dir, dirlen) == 0 && - (realdir[dirlen] == '/' || realdir[dirlen] == '\0')) - return 1; - return 0; -} - -/* - * List words in stringlist, vertically arranged - */ -void -list_vertical(StringList *sl) -{ - size_t i, j; - size_t columns, lines; - char *p; - size_t w, width; - - 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; - } - if (p) { - 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) -{ - socklen_t slen; - - if (0 == rcvbuf_size) { - slen = sizeof(rcvbuf_size); - if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (void *)&rcvbuf_size, &slen) == -1) - err(1, "Unable to determine rcvbuf size"); - if (rcvbuf_size <= 0) - rcvbuf_size = 8 * 1024; - if (rcvbuf_size > 8 * 1024 * 1024) - rcvbuf_size = 8 * 1024 * 1024; - DPRINTF("setupsockbufsize: rcvbuf_size determined as %d\n", - rcvbuf_size); - } - if (0 == sndbuf_size) { - slen = sizeof(sndbuf_size); - if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF, - (void *)&sndbuf_size, &slen) == -1) - err(1, "Unable to determine sndbuf size"); - if (sndbuf_size <= 0) - sndbuf_size = 8 * 1024; - if (sndbuf_size > 8 * 1024 * 1024) - sndbuf_size = 8 * 1024 * 1024; - DPRINTF("setupsockbufsize: sndbuf_size determined as %d\n", - sndbuf_size); - } - - 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) -{ - size_t di, si; - - di = si = 0; - while (src[si] != '\0' && di < dstlen && si < srclen) { - switch (src[si]) { - case '\\': - case ' ': - case '\t': - case '\r': - case '\n': - case '"': - /* - * Need room for two characters and NUL, avoiding - * incomplete escape sequences at end of dst. - */ - if (di >= dstlen - 3) - break; - dst[di++] = '\\'; - /* FALLTHROUGH */ - default: - dst[di] = src[si++]; - if (di < dstlen) - di++; - } - } - 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, *p2, *q; - size_t i; - int 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 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 && hostname ? hostname : "-"; - *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'; -} - -/* - * 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 = AF_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); - } - DPRINTF("isipv6addr: got %d for %s\n", rv, addr); -#endif - return (rv == 1) ? 1 : 0; -} - -/* - * Read a line from the FILE stream into buf/buflen using fgets(), so up - * to buflen-1 chars will be read and the result will be NUL terminated. - * If the line has a trailing newline it will be removed. - * If the line is too long, excess characters will be read until - * newline/EOF/error. - * If EOF/error occurs or a too-long line is encountered and errormsg - * isn't NULL, it will be changed to a description of the problem. - * (The EOF message has a leading \n for cosmetic purposes). - * Returns: - * >=0 length of line (excluding trailing newline) if all ok - * -1 error occurred - * -2 EOF encountered - * -3 line was too long - */ -int -get_line(FILE *stream, char *buf, size_t buflen, const char **errormsg) -{ - int rv, ch; - size_t len; - - if (fgets(buf, buflen, stream) == NULL) { - if (feof(stream)) { /* EOF */ - rv = -2; - if (errormsg) - *errormsg = "\nEOF received"; - } else { /* error */ - rv = -1; - if (errormsg) - *errormsg = "Error encountered"; - } - clearerr(stream); - return rv; - } - len = strlen(buf); - if (buf[len-1] == '\n') { /* clear any trailing newline */ - buf[--len] = '\0'; - } else if (len == buflen-1) { /* line too long */ - while ((ch = getchar()) != '\n' && ch != EOF) - continue; - if (errormsg) - *errormsg = "Input line is too long"; - clearerr(stream); - return -3; - } - if (errormsg) - *errormsg = NULL; - return len; -} - -/* - * Internal version of connect(2); sets socket buffer sizes, - * binds to a specific local address (if set), and - * supports a connection timeout using a non-blocking connect(2) with - * a poll(2). - * Socket fcntl flags are temporarily updated to include O_NONBLOCK; - * these will not be reverted on connection failure. - * Returns 0 on success, or -1 upon failure (with an appropriate - * error message displayed.) - */ -int -ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen, int pe) -{ - int flags, rv, timeout, error; - socklen_t slen; - struct timeval endtime, now, td; - struct pollfd pfd[1]; - char hname[NI_MAXHOST]; - char sname[NI_MAXSERV]; - - setupsockbufsize(sock); - if (getnameinfo(name, namelen, - hname, sizeof(hname), sname, sizeof(sname), - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - strlcpy(hname, "?", sizeof(hname)); - strlcpy(sname, "?", sizeof(sname)); - } - - if (bindai != NULL) { /* bind to specific addr */ - struct addrinfo *ai; - - for (ai = bindai; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family == name->sa_family) - break; - } - if (ai == NULL) - ai = bindai; - if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { - char bname[NI_MAXHOST]; - int saveerr; - - saveerr = errno; - if (getnameinfo(ai->ai_addr, ai->ai_addrlen, - bname, sizeof(bname), NULL, 0, NI_NUMERICHOST) != 0) - strlcpy(bname, "?", sizeof(bname)); - errno = saveerr; - warn("Can't bind to `%s'", bname); - return -1; - } - } - - /* save current socket flags */ - if ((flags = fcntl(sock, F_GETFL, 0)) == -1) { - warn("Can't %s socket flags for connect to `%s:%s'", - "save", hname, sname); - return -1; - } - /* set non-blocking connect */ - if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) { - warn("Can't set socket non-blocking for connect to `%s:%s'", - hname, sname); - return -1; - } - - /* 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" */ - if (pe || (errno != EHOSTUNREACH)) - connecterror: - warn("Can't connect to `%s:%s'", hname, sname); - 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 = ftp_poll(pfd, 1, timeout); - /* loop until poll ! EINTR */ - } while (rv == -1 && errno == EINTR); - - if (rv == 0) { /* poll (connect) timed out */ - errno = ETIMEDOUT; - goto connecterror; - } - - if (rv == -1) { /* poll error */ - goto connecterror; - } else if (pfd[0].revents & (POLLIN|POLLOUT)) { - slen = sizeof(error); /* OK, or pending error */ - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, - &error, &slen) == -1) { - /* Solaris pending error */ - goto connecterror; - } else if (error != 0) { - errno = error; /* BSD pending error */ - goto connecterror; - } - } else { - errno = EBADF; /* this shouldn't happen ... */ - goto connecterror; - } - } - - if (fcntl(sock, F_SETFL, flags) == -1) { - /* restore socket flags */ - warn("Can't %s socket flags for connect to `%s:%s'", - "restore", hname, sname); - return -1; - } - return 0; -} - -/* - * Internal version of listen(2); sets socket buffer sizes first. - */ -int -ftp_listen(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 -ftp_poll(struct pollfd *fds, int nfds, int timeout) -{ - return poll(fds, nfds, timeout); -} - -/* - * malloc() with inbuilt error checking - */ -void * -ftp_malloc(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 * -ftp_sl_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 -ftp_sl_add(StringList *sl, char *i) -{ - - sl_add(sl, i); -} - -/* - * strdup() with inbuilt error checking - */ -char * -ftp_strdup(const char *str) -{ - char *s; - - if (str == NULL) - errx(1, "ftp_strdup: 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/version.h b/contrib/tnftp/version.h deleted file mode 100644 index 9fb6c4ab3e..0000000000 --- a/contrib/tnftp/version.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $NetBSD: version.h,v 1.84 2013/05/05 10:40:19 lukem Exp $ */ - -/*- - * Copyright (c) 1999-2009 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. - * - * 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 "20130220" -#endif -- 2.41.0