Connect lukemftp to the build as the default ftp client. Lukemftp

supports most of the previous features of FreeBSD ftp, but has been
better maintained and includes new features.
This commit is contained in:
Mike Heffner 2001-12-13 23:46:44 +00:00
parent 9446b36bab
commit bfacd15a50
14 changed files with 6 additions and 9453 deletions

View File

@ -6,13 +6,16 @@
#
#CFLAGS+=-DGATE_SERVER=\"ftp-gw.host\" # -DGATE_PORT=21
LUKEMFTP= ${.CURDIR}/../../contrib/lukemftp
.PATH: ${LUKEMFTP}/src
PROG= ftp
SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c ruserpass.c \
util.c
CFLAGS+=-DINET6
LDADD+= -ledit -ltermcap
DPADD+= ${LIBEDIT} ${LIBTERMCAP}
CFLAGS+=-I${.CURDIR} -I${LUKEMFTP}
LDADD+= -ledit -ltermcap -lutil
DPADD+= ${LIBEDIT} ${LIBTERMCAP} ${LIBUTIL}
LINKS= ${BINDIR}/ftp ${BINDIR}/pftp \
${BINDIR}/ftp ${BINDIR}/gate-ftp

File diff suppressed because it is too large Load Diff

View File

@ -1,230 +0,0 @@
/* $NetBSD: cmdtab.c,v 1.17 1997/08/18 10:20:17 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94";
#else
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: cmdtab.c,v 1.17 1997/08/18 10:20:17 lukem Exp $");
#endif
#endif /* not lint */
#include <stdio.h>
#include "ftp_var.h"
/*
* User FTP -- Command Tables.
*/
char accounthelp[] = "send account command to remote server";
char appendhelp[] = "append to a file";
char asciihelp[] = "set ascii transfer type";
char beephelp[] = "beep when command completed";
char binaryhelp[] = "set binary transfer type";
char casehelp[] = "toggle mget upper/lower case id mapping";
char cdhelp[] = "change remote working directory";
char cduphelp[] = "change remote working directory to parent directory";
char chmodhelp[] = "change file permissions of remote file";
char connecthelp[] = "connect to remote ftp server";
char crhelp[] = "toggle carriage return stripping on ascii gets";
char debughelp[] = "toggle/set debugging mode";
char deletehelp[] = "delete remote file";
char dirhelp[] = "list contents of remote directory";
char disconhelp[] = "terminate ftp session";
char domachelp[] = "execute macro";
#ifndef SMALL
char edithelp[] = "toggle command line editing";
#endif /* !SMALL */
char formhelp[] = "set file transfer format";
char gatehelp[] = "toggle gate-ftp; specify host[:port] to change proxy";
char globhelp[] = "toggle metacharacter expansion of local file names";
char hashhelp[] = "toggle printing `#' marks; specify number to set size";
char helphelp[] = "print local help information";
char idlehelp[] = "get (set) idle timer on remote side";
char lcdhelp[] = "change local working directory";
char lpwdhelp[] = "print local working directory";
char lshelp[] = "list contents of remote directory";
char macdefhelp[] = "define a macro";
char mdeletehelp[] = "delete multiple files";
char mdirhelp[] = "list contents of multiple remote directories";
char mgethelp[] = "get multiple files";
char mkdirhelp[] = "make directory on the remote machine";
char mlshelp[] = "list contents of multiple remote directories";
char modehelp[] = "set file transfer mode";
char modtimehelp[] = "show last modification time of remote file";
char mputhelp[] = "send multiple files";
char newerhelp[] = "get file if remote file is newer than local file ";
char nlisthelp[] = "nlist contents of remote directory";
char nmaphelp[] = "set templates for default file name mapping";
char ntranshelp[] = "set translation table for default file name mapping";
char pagehelp[] = "view a remote file through your pager";
char passivehelp[] = "enter passive transfer mode";
char porthelp[] = "toggle use of PORT cmd for each data connection";
char preservehelp[] ="toggle preservation of modification time of "
"retreived files";
char progresshelp[] ="toggle transfer progress meter";
char prompthelp[] = "force interactive prompting on multiple commands";
char proxyhelp[] = "issue command on alternate connection";
char pwdhelp[] = "print working directory on remote machine";
char quithelp[] = "terminate ftp session and exit";
char quotehelp[] = "send arbitrary ftp command";
char receivehelp[] = "receive file";
char regethelp[] = "get file restarting at end of local file";
char remotehelp[] = "get help from remote server";
char renamehelp[] = "rename file";
char resethelp[] = "clear queued command replies";
char restarthelp[]= "restart file transfer at bytecount";
char restricthelp[]= "toggle restriction of data port range";
char rmdirhelp[] = "remove directory on the remote machine";
char rmtstatushelp[]="show status of remote machine";
char runiquehelp[] = "toggle store unique for local files";
char sendhelp[] = "send one file";
char shellhelp[] = "escape to the shell";
char sitehelp[] = "send site specific command to remote server\n"
"\t\tTry \"rhelp site\" or \"site help\" "
"for more information";
char sizecmdhelp[] = "show size of remote file";
char statushelp[] = "show current status";
char structhelp[] = "set file transfer structure";
char suniquehelp[] = "toggle store unique on remote machine";
char systemhelp[] = "show remote system type";
char tenexhelp[] = "set tenex file transfer type";
char tracehelp[] = "toggle packet tracing";
char typehelp[] = "set file transfer type";
char umaskhelp[] = "get (set) umask on remote side";
char userhelp[] = "send new user information";
char verbosehelp[] = "toggle verbose mode";
#ifdef SMALL
#define CMPL(x)
#define CMPL0
#else /* !SMALL */
#define CMPL(x) __STRING(x),
#define CMPL0 "",
#endif /* !SMALL */
struct cmd cmdtab[] = {
{ "!", shellhelp, 0, 0, 0, CMPL0 shell },
{ "$", domachelp, 1, 0, 0, CMPL0 domacro },
{ "account", accounthelp, 0, 1, 1, CMPL0 account},
{ "append", appendhelp, 1, 1, 1, CMPL(lr) put },
{ "ascii", asciihelp, 0, 1, 1, CMPL0 setascii },
{ "bell", beephelp, 0, 0, 0, CMPL0 setbell },
{ "binary", binaryhelp, 0, 1, 1, CMPL0 setbinary },
{ "bye", quithelp, 0, 0, 0, CMPL0 quit },
{ "case", casehelp, 0, 0, 1, CMPL0 setcase },
{ "cd", cdhelp, 0, 1, 1, CMPL(r) cd },
{ "cdup", cduphelp, 0, 1, 1, CMPL0 cdup },
{ "chmod", chmodhelp, 0, 1, 1, CMPL(nr) do_chmod },
{ "close", disconhelp, 0, 1, 1, CMPL0 disconnect },
{ "cr", crhelp, 0, 0, 0, CMPL0 setcr },
{ "debug", debughelp, 0, 0, 0, CMPL0 setdebug },
{ "delete", deletehelp, 0, 1, 1, CMPL(r) delete },
{ "dir", dirhelp, 1, 1, 1, CMPL(rl) ls },
{ "disconnect", disconhelp, 0, 1, 1, CMPL0 disconnect },
#ifndef SMALL
{ "edit", edithelp, 0, 0, 0, CMPL0 setedit },
#endif /* !SMALL */
{ "exit", quithelp, 0, 0, 0, CMPL0 quit },
{ "form", formhelp, 0, 1, 1, CMPL0 setform },
{ "ftp", connecthelp, 0, 0, 1, CMPL0 setpeer },
{ "get", receivehelp, 1, 1, 1, CMPL(rl) get },
{ "gate", gatehelp, 0, 0, 0, CMPL0 setgate },
{ "glob", globhelp, 0, 0, 0, CMPL0 setglob },
{ "hash", hashhelp, 0, 0, 0, CMPL0 sethash },
{ "help", helphelp, 0, 0, 1, CMPL(C) help },
{ "idle", idlehelp, 0, 1, 1, CMPL0 idle },
{ "image", binaryhelp, 0, 1, 1, CMPL0 setbinary },
{ "lcd", lcdhelp, 0, 0, 0, CMPL(l) lcd },
{ "less", pagehelp, 1, 1, 1, CMPL(r) page },
{ "lpwd", lpwdhelp, 0, 0, 0, CMPL0 lpwd },
{ "ls", lshelp, 1, 1, 1, CMPL(rl) ls },
{ "macdef", macdefhelp, 0, 0, 0, CMPL0 macdef },
{ "mdelete", mdeletehelp, 1, 1, 1, CMPL(R) mdelete },
{ "mdir", mdirhelp, 1, 1, 1, CMPL(R) mls },
{ "mget", mgethelp, 1, 1, 1, CMPL(R) mget },
{ "mkdir", mkdirhelp, 0, 1, 1, CMPL(r) makedir },
{ "mls", mlshelp, 1, 1, 1, CMPL(R) mls },
{ "mode", modehelp, 0, 1, 1, CMPL0 setftmode },
{ "modtime", modtimehelp, 0, 1, 1, CMPL(r) modtime },
{ "more", pagehelp, 1, 1, 1, CMPL(r) page },
{ "mput", mputhelp, 1, 1, 1, CMPL(L) mput },
{ "msend", mputhelp, 1, 1, 1, CMPL(L) mput },
{ "newer", newerhelp, 1, 1, 1, CMPL(r) newer },
{ "nlist", nlisthelp, 1, 1, 1, CMPL(rl) ls },
{ "nmap", nmaphelp, 0, 0, 1, CMPL0 setnmap },
{ "ntrans", ntranshelp, 0, 0, 1, CMPL0 setntrans },
{ "open", connecthelp, 0, 0, 1, CMPL0 setpeer },
{ "page", pagehelp, 1, 1, 1, CMPL(r) page },
{ "passive", passivehelp, 0, 0, 0, CMPL0 setpassive },
{ "preserve", preservehelp, 0, 0, 0, CMPL0 setpreserve },
{ "progress", progresshelp, 0, 0, 0, CMPL0 setprogress },
{ "prompt", prompthelp, 0, 0, 0, CMPL0 setprompt },
{ "proxy", proxyhelp, 0, 0, 1, CMPL(c) doproxy },
{ "put", sendhelp, 1, 1, 1, CMPL(lr) put },
{ "pwd", pwdhelp, 0, 1, 1, CMPL0 pwd },
{ "quit", quithelp, 0, 0, 0, CMPL0 quit },
{ "quote", quotehelp, 1, 1, 1, CMPL0 quote },
{ "recv", receivehelp, 1, 1, 1, CMPL(rl) get },
{ "reget", regethelp, 1, 1, 1, CMPL(rl) reget },
{ "rename", renamehelp, 0, 1, 1, CMPL(rr) renamefile },
{ "reset", resethelp, 0, 1, 1, CMPL0 reset },
{ "restart", restarthelp, 1, 1, 1, CMPL0 restart },
{ "restrict", restricthelp, 0, 0, 0, CMPL0 setrestrict },
{ "rhelp", remotehelp, 0, 1, 1, CMPL0 rmthelp },
{ "rmdir", rmdirhelp, 0, 1, 1, CMPL(r) removedir },
{ "rstatus", rmtstatushelp, 0, 1, 1, CMPL(r) rmtstatus },
{ "runique", runiquehelp, 0, 0, 1, CMPL0 setrunique },
{ "send", sendhelp, 1, 1, 1, CMPL(lr) put },
{ "sendport", porthelp, 0, 0, 0, CMPL0 setport },
{ "site", sitehelp, 0, 1, 1, CMPL0 site },
{ "size", sizecmdhelp, 1, 1, 1, CMPL(r) sizecmd },
{ "status", statushelp, 0, 0, 1, CMPL0 status },
{ "struct", structhelp, 0, 1, 1, CMPL0 setstruct },
{ "sunique", suniquehelp, 0, 0, 1, CMPL0 setsunique },
{ "system", systemhelp, 0, 1, 1, CMPL0 syst },
{ "tenex", tenexhelp, 0, 1, 1, CMPL0 settenex },
{ "trace", tracehelp, 0, 0, 0, CMPL0 settrace },
{ "type", typehelp, 0, 1, 1, CMPL0 settype },
{ "umask", umaskhelp, 0, 1, 1, CMPL0 do_umask },
{ "user", userhelp, 0, 1, 1, CMPL0 user },
{ "verbose", verbosehelp, 0, 0, 0, CMPL0 setverbose },
{ "?", helphelp, 0, 0, 1, CMPL(C) help },
{ 0 },
};
int NCMDS = (sizeof(cmdtab) / sizeof(cmdtab[0])) - 1;

View File

@ -1,377 +0,0 @@
/* $NetBSD: complete.c,v 1.11 1997/09/13 09:05:53 lukem Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SMALL
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: complete.c,v 1.11 1997/09/13 09:05:53 lukem Exp $");
#endif /* not lint */
/*
* FTP user program - command and file completion routines
*/
#include <sys/types.h>
#include <ctype.h>
#include <err.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ftp_var.h"
static int
comparstr(a, b)
const void *a, *b;
{
return (strcoll(*(char **)a, *(char **)b));
}
/*
* Determine if complete is ambiguous. If unique, insert.
* If no choices, error. If unambiguous prefix, insert that.
* Otherwise, list choices. words is assumed to be filtered
* to only contain possible choices.
* Args:
* word word which started the match
* list list by default
* words stringlist containing possible matches
*/
static unsigned char
complete_ambiguous(word, list, words)
char *word;
int list;
StringList *words;
{
char insertstr[2 * MAXPATHLEN];
char *lastmatch;
int i, j;
size_t matchlen, wordlen;
wordlen = strlen(word);
if (words->sl_cur == 0)
return (CC_ERROR); /* no choices available */
if (words->sl_cur == 1) { /* only once choice available */
for (i = 0, j = 0; words->sl_str[0][i] != '\0'; i++) {
if (isspace((u_char)words->sl_str[0][i]))
insertstr[j++] = '\\';
insertstr[j++] = words->sl_str[0][i];
}
insertstr[j] = '\0';
if (el_insertstr(el, insertstr + wordlen) == -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) {
(void)strncpy(insertstr, lastmatch, matchlen);
insertstr[matchlen] = '\0';
if (el_insertstr(el, insertstr + wordlen) == -1)
return (CC_ERROR);
else
/*
* XXX: really want CC_REFRESH_BEEP
*/
return (CC_REFRESH);
}
}
putchar('\n');
qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr);
list_vertical(words);
return (CC_REDISPLAY);
}
/*
* Complete a command
*/
static unsigned char
complete_command(word, list)
char *word;
int list;
{
struct cmd *c;
StringList *words;
size_t wordlen;
unsigned char rv;
words = 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)
sl_add(words, c->c_name);
}
rv = complete_ambiguous(word, list, words);
sl_free(words, 0);
return (rv);
}
/*
* Complete a local file
*/
static unsigned char
complete_local(word, list)
char *word;
int list;
{
StringList *words;
char dir[MAXPATHLEN];
char *file;
DIR *dd;
struct dirent *dp;
unsigned char rv;
if ((file = strrchr(word, '/')) == NULL) {
dir[0] = '.';
dir[1] = '\0';
file = word;
} else {
if (file == word) {
dir[0] = '/';
dir[1] = '\0';
} else {
(void)strncpy(dir, word, file - word);
dir[file - word] = '\0';
}
file++;
}
if ((dd = opendir(dir)) == NULL)
return (CC_ERROR);
words = sl_init();
for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
continue;
if (strlen(file) > dp->d_namlen)
continue;
if (strncmp(file, dp->d_name, strlen(file)) == 0) {
char *tcp;
tcp = strdup(dp->d_name);
if (tcp == NULL)
errx(1, "Can't allocate memory for local dir");
sl_add(words, tcp);
}
}
closedir(dd);
rv = complete_ambiguous(file, list, words);
sl_free(words, 1);
return (rv);
}
/*
* Complete a remote file
*/
static unsigned char
complete_remote(word, list)
char *word;
int list;
{
static StringList *dirlist;
static char lastdir[MAXPATHLEN];
StringList *words;
char dir[MAXPATHLEN];
char *file, *cp;
int i;
unsigned char rv;
char *dummyargv[] = { "complete", dir, NULL };
if ((file = strrchr(word, '/')) == NULL) {
dir[0] = '.';
dir[1] = '\0';
file = word;
} else {
cp = file;
while (*cp == '/' && cp > word)
cp--;
(void)strncpy(dir, word, cp - word + 1);
dir[cp - word + 1] = '\0';
file++;
}
if (dirchange || strcmp(dir, lastdir) != 0) { /* dir not cached */
char *emesg;
if (dirlist != NULL)
sl_free(dirlist, 1);
dirlist = 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 = strdup(tcp);
if (tcp == NULL)
errx(1, "Can't allocate memory for remote dir");
sl_add(dirlist, tcp);
}
if (emesg != NULL) {
printf("\n%s\n", emesg);
return (CC_REDISPLAY);
}
(void)strcpy(lastdir, dir);
dirchange = 0;
}
words = 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)
sl_add(words, cp);
}
rv = complete_ambiguous(file, list, words);
sl_free(words, 0);
return (rv);
}
/*
* Generic complete routine
*/
unsigned char
complete(el, ch)
EditLine *el;
int ch;
{
static char word[FTPBUFLEN];
static int lastc_argc, lastc_argo;
struct cmd *c;
const LineInfo *lf;
int celems, dolist;
size_t len;
lf = el_line(el);
len = lf->lastchar - lf->buffer;
if (len >= sizeof(line))
return (CC_ERROR);
(void)strncpy(line, lf->buffer, len);
line[len] = '\0';
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], cursor_argo) == 0)
dolist = 1;
else
(void)strncpy(word, margv[cursor_argc], cursor_argo);
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);
switch (c->c_complete[cursor_argc - 1]) {
case 'l': /* local complete */
case 'L':
return (complete_local(word, dolist));
case 'r': /* remote complete */
case 'R':
if (connected != -1) {
puts("\nMust be logged in to complete.");
return (CC_REDISPLAY);
}
return (complete_remote(word, dolist));
case 'c': /* command complete */
case 'C':
return (complete_command(word, dolist));
case 'n': /* no complete */
default:
return (CC_ERROR);
}
return (CC_ERROR);
}
#endif /* !SMALL */

View File

@ -1,155 +0,0 @@
/* $NetBSD: domacro.c,v 1.10 1997/07/20 09:45:45 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: domacro.c,v 1.10 1997/07/20 09:45:45 lukem Exp $");
#endif
#endif /* not lint */
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include "ftp_var.h"
void
domacro(argc, argv)
int argc;
char *argv[];
{
int i, j, count = 2, loopflg = 0;
char *cp1, *cp2, line2[200];
struct cmd *c;
if (argc < 2 && !another(&argc, &argv, "macro name")) {
printf("usage: %s macro_name\n", argv[0]);
code = -1;
return;
}
for (i = 0; i < macnum; ++i) {
if (!strncmp(argv[1], macros[i].mac_name, 9)) {
break;
}
}
if (i == macnum) {
printf("'%s' macro not found.\n", argv[1]);
code = -1;
return;
}
(void)strcpy(line2, line);
TOP:
cp1 = macros[i].mac_start;
while (cp1 != macros[i].mac_end) {
while (isascii(*cp1) && isspace(*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)strcpy(cp2, argv[j+1]);
cp2 += strlen(argv[j+1]);
}
break;
}
if (*(cp1+1) == 'i') {
loopflg = 1;
cp1++;
if (count < argc) {
(void)strcpy(cp2, argv[count]);
cp2 += strlen(argv[count]);
}
break;
}
/* intentional drop through */
default:
*cp2++ = *cp1;
break;
}
if (*cp1 != '\0') {
cp1++;
}
}
*cp2 = '\0';
makeargv();
c = getcmd(margv[0]);
if (c == (struct cmd *)-1) {
puts("?Ambiguous command.");
code = -1;
}
else if (c == 0) {
puts("?Invalid command.");
code = -1;
}
else if (c->c_conn && !connected) {
puts("Not connected.");
code = -1;
}
else {
if (verbose)
puts(line);
(*c->c_handler)(margc, margv);
if (bell && c->c_bell) {
(void)putchar('\007');
}
(void)strcpy(line, line2);
makeargv();
argc = margc;
argv = margv;
}
if (cp1 != macros[i].mac_end) {
cp1++;
}
}
if (loopflg && ++count < argc) {
goto TOP;
}
}

View File

@ -1,176 +0,0 @@
/* $FreeBSD$ */
/* $NetBSD: extern.h,v 1.17.2.1 1997/11/18 00:59:50 mellon Exp $ */
/*-
* Copyright (c) 1994 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)extern.h 8.3 (Berkeley) 10/9/94
*/
void abort_remote __P((FILE *));
void abortpt __P((int));
void abortrecv __P((int));
void abortsend __P((int));
void account __P((int, char **));
void ai_unmapped __P((struct addrinfo *));
void alarmtimer __P((int));
int another __P((int *, char ***, const char *));
int auto_fetch __P((int, char **));
void blkfree __P((char **));
void cd __P((int, char **));
void cdup __P((int, char **));
void changetype __P((int, int));
void cmdabort __P((int));
void cmdscanner __P((int));
int command __P((const char *, ...));
#ifndef SMALL
unsigned char complete __P((EditLine *, int));
void controlediting __P((void));
#endif /* !SMALL */
int confirm __P((const char *, const char *));
FILE *dataconn __P((const char *));
void delete __P((int, char **));
void disconnect __P((int, char **));
void do_chmod __P((int, char **));
void do_umask __P((int, char **));
void domacro __P((int, char **));
char *domap __P((char *));
void doproxy __P((int, char **));
char *dotrans __P((char *));
int empty __P((fd_set *, int));
void get __P((int, char **));
struct cmd *getcmd __P((const char *));
int getit __P((int, char **, int, const char *));
int getreply __P((int));
int globulize __P((char **));
char *gunique __P((const char *));
void help __P((int, char **));
char *hookup __P((const char *, char *));
void idle __P((int, char **));
int initconn __P((void));
void intr __P((void));
int isipv6addr __P((const char *));
void list_vertical __P((StringList *));
void lcd __P((int, char **));
int login __P((const char *, char *, char *));
void lostpeer __P((void));
void lpwd __P((int, char **));
void ls __P((int, char **));
void mabort __P((int));
void macdef __P((int, char **));
void makeargv __P((void));
void makedir __P((int, char **));
void mdelete __P((int, char **));
void mget __P((int, char **));
void mls __P((int, char **));
void modtime __P((int, char **));
void mput __P((int, char **));
char *onoff __P((int));
void newer __P((int, char **));
void page __P((int, char **));
void progressmeter __P((int));
char *prompt __P((void));
void proxabort __P((int));
void proxtrans __P((const char *, const char *, const char *));
void psabort __P((int));
void psummary __P((int));
void pswitch __P((int));
void ptransfer __P((int));
void put __P((int, char **));
void pwd __P((int, char **));
void quit __P((int, char **));
void quote __P((int, char **));
void quote1 __P((const char *, int, char **));
void recvrequest __P((const char *, const char *, const char *,
const char *, int, int));
void reget __P((int, char **));
char *remglob __P((char **, int, char **));
off_t remotesize __P((const char *, int));
time_t remotemodtime __P((const char *, int));
void removedir __P((int, char **));
void renamefile __P((int, char **));
void reset __P((int, char **));
void restart __P((int, char **));
void rmthelp __P((int, char **));
void rmtstatus __P((int, char **));
int ruserpass __P((const char *, char **, char **, char **));
void sendrequest __P((const char *, const char *, const char *, int));
void setascii __P((int, char **));
void setbell __P((int, char **));
void setbinary __P((int, char **));
void setcase __P((int, char **));
void setcr __P((int, char **));
void setdebug __P((int, char **));
void setedit __P((int, char **));
void setform __P((int, char **));
void setftmode __P((int, char **));
void setgate __P((int, char **));
void setglob __P((int, char **));
void sethash __P((int, char **));
void setnmap __P((int, char **));
void setntrans __P((int, char **));
void setpassive __P((int, char **));
void setpeer __P((int, char **));
void setport __P((int, char **));
void setpreserve __P((int, char **));
void setprogress __P((int, char **));
void setprompt __P((int, char **));
void setrestrict __P((int, char **));
void setrunique __P((int, char **));
void setstruct __P((int, char **));
void setsunique __P((int, char **));
void settenex __P((int, char **));
void settrace __P((int, char **));
void setttywidth __P((int));
void settype __P((int, char **));
void setverbose __P((int, char **));
void shell __P((int, char **));
void site __P((int, char **));
void sizecmd __P((int, char **));
char *slurpstring __P((void));
void status __P((int, char **));
void syst __P((int, char **));
int togglevar __P((int, char **, int *, const char *));
void usage __P((void));
void user __P((int, char **));
extern struct cmd cmdtab[];
extern FILE *cout;
extern int data;
extern char *home;
extern int family;
extern int proxy;
extern char reply_string[];
extern int NCMDS;
extern char *__progname; /* from crt0.o */

View File

@ -1,733 +0,0 @@
/* $NetBSD: fetch.c,v 1.16.2.1 1997/11/18 01:00:22 mellon Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason Thorpe and Luke Mewburn.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: fetch.c,v 1.16.2.1 1997/11/18 01:00:22 mellon Exp $");
#endif /* not lint */
/*
* FTP User Program -- Command line file retrieval
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/ftp.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <vis.h>
#include "ftp_var.h"
/* wrapper for KAME-special getnameinfo() */
#ifndef NI_WITHSCOPEID
#define NI_WITHSCOPEID 0
#endif
static int url_get __P((const char *, const char *));
void aborthttp __P((int));
#define FTP_URL "ftp://" /* ftp URL prefix */
#define HTTP_URL "http://" /* http URL prefix */
#define FTP_PROXY "ftp_proxy" /* env var with ftp proxy location */
#define HTTP_PROXY "http_proxy" /* env var with http proxy location */
#define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0'))
jmp_buf httpabort;
/*
* Retrieve URL, via the proxy in $proxyvar if necessary.
* Modifies the string argument given.
* Returns -1 on failure, 0 on success
*/
static int
url_get(origline, proxyenv)
const char *origline;
const char *proxyenv;
{
struct addrinfo hints;
struct addrinfo *res0, *res;
char nameinfo[2 * INET6_ADDRSTRLEN + 1];
int i, out, isftpurl;
char *port;
volatile int s;
size_t len;
char c, *cp, *ep, *http_buffer, *portnum, *path, *uri, buf[4096];
const char *savefile;
char *line, *proxy, *host;
volatile sig_t oldintr;
off_t hashbytes;
int error;
s = -1;
proxy = NULL;
isftpurl = 0;
res0 = NULL;
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */
(void)&savefile;
(void)&proxy;
(void)&res0;
#endif
line = strdup(origline);
if (line == NULL)
errx(1, "Can't allocate memory to parse URL");
if (strncasecmp(line, HTTP_URL, sizeof(HTTP_URL) - 1) == 0)
host = line + sizeof(HTTP_URL) - 1;
else if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
host = line + sizeof(FTP_URL) - 1;
isftpurl = 1;
} else
errx(1, "url_get: Invalid URL '%s'", line);
path = strchr(host, '/'); /* find path */
if (EMPTYSTRING(path)) {
if (isftpurl)
goto noftpautologin;
warnx("Invalid URL (no `/' after host): %s", origline);
goto cleanup_url_get;
}
*path++ = '\0';
if (EMPTYSTRING(path)) {
if (isftpurl)
goto noftpautologin;
warnx("Invalid URL (no file after host): %s", origline);
goto cleanup_url_get;
}
savefile = strrchr(path, '/'); /* find savefile */
if (savefile != NULL)
savefile++;
else
savefile = path;
if (EMPTYSTRING(savefile)) {
if (isftpurl)
goto noftpautologin;
warnx("Invalid URL (no file after directory): %s", origline);
goto cleanup_url_get;
}
uri = (char *) calloc(strlen(path) * 4 + 1, sizeof(char));
if (uri == NULL)
errx(1, "Can't allocate memory for URI.");
strvisx(uri, path, strlen(path), VIS_HTTPSTYLE);
if (proxyenv != NULL) { /* use proxy */
proxy = strdup(proxyenv);
if (proxy == NULL)
errx(1, "Can't allocate memory for proxy URL.");
if (strncasecmp(proxy, HTTP_URL, sizeof(HTTP_URL) - 1) == 0)
host = proxy + sizeof(HTTP_URL) - 1;
else if (strncasecmp(proxy, FTP_URL, sizeof(FTP_URL) - 1) == 0)
host = proxy + sizeof(FTP_URL) - 1;
else {
warnx("Malformed proxy URL: %s", proxyenv);
goto cleanup_url_get;
}
if (EMPTYSTRING(host)) {
warnx("Malformed proxy URL: %s", proxyenv);
goto cleanup_url_get;
}
*--path = '/'; /* add / back to real path */
path = strchr(host, '/'); /* remove trailing / on host */
if (! EMPTYSTRING(path))
*path++ = '\0';
path = line;
}
if (*host == '[' && (portnum = strrchr(host, ']'))) { /* IPv6 URL */
*portnum++ = '\0';
host++;
if (*portnum == ':')
portnum++;
else
portnum = NULL;
} else {
portnum = strrchr(host, ':'); /* find portnum */
if (portnum != NULL)
*portnum++ = '\0';
}
if (debug)
printf("host %s, port %s, path %s, save as %s.\n",
host, portnum, uri, savefile);
if (! EMPTYSTRING(portnum)) {
port = portnum;
} else
port = httpport;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host, port, &hints, &res);
res0 = res;
if (error) {
warnx("%s: %s", host, gai_strerror(error));
if (error == EAI_SYSTEM)
warnx("%s: %s", host, strerror(errno));
goto cleanup_url_get;
}
while (1)
{
ai_unmapped(res);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s == -1) {
res = res->ai_next;
if (res)
continue;
warn("Can't create socket");
goto cleanup_url_get;
}
if (dobind) {
struct addrinfo *bindres;
int binderr = -1;
for (bindres = bindres0;
bindres != NULL;
bindres = bindres->ai_next)
if (bindres->ai_family == res->ai_family)
break;
if (bindres == NULL)
bindres = bindres0;
binderr = bind(s, bindres->ai_addr, bindres->ai_addrlen);
if (binderr == -1)
{
res = res->ai_next;
if (res) {
(void)close(s);
continue;
}
getnameinfo(bindres->ai_addr, bindres->ai_addrlen,
nameinfo, sizeof(nameinfo), NULL, 0,
NI_NUMERICHOST|NI_WITHSCOPEID);
/* XXX check error? */
warn("Can't bind to %s", nameinfo);
goto cleanup_url_get;
}
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
res = res->ai_next;
if (res) {
(void)close(s);
continue;
}
warn("Can't connect to %s", host);
goto cleanup_url_get;
}
break;
}
freeaddrinfo(res0);
res0 = NULL;
/*
* Construct and send the request. We're expecting a return
* status of "200". Proxy requests don't want leading /.
*/
if (!proxy) {
printf("Requesting %s\n", origline);
len = asprintf(&http_buffer,
"GET /%s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", uri, host);
} else {
printf("Requesting %s (via %s)\n", origline, proxyenv);
len = asprintf(&http_buffer,
"GET %s HTTP/1.0\r\n\r\n", path);
}
free(uri);
if (len < 0) {
warnx("Failed to format HTTP request");
goto cleanup_url_get;
}
if (write(s, http_buffer, len) < len) {
warn("Writing HTTP request");
free(http_buffer);
goto cleanup_url_get;
}
free(http_buffer);
memset(buf, 0, sizeof(buf));
for (cp = buf; cp < buf + sizeof(buf); ) {
if (read(s, cp, 1) != 1)
goto improper;
if (*cp == '\r')
continue;
if (*cp == '\n')
break;
cp++;
}
buf[sizeof(buf) - 1] = '\0'; /* sanity */
cp = strchr(buf, ' ');
if (cp == NULL)
goto improper;
else
cp++;
if (strncmp(cp, "200", 3)) {
warnx("Error retrieving file: %s", cp);
goto cleanup_url_get;
}
/*
* Read the rest of the header.
*/
memset(buf, 0, sizeof(buf));
c = '\0';
for (cp = buf; cp < buf + sizeof(buf); ) {
if (read(s, cp, 1) != 1)
goto improper;
if (*cp == '\r')
continue;
if (*cp == '\n' && c == '\n')
break;
c = *cp;
cp++;
}
buf[sizeof(buf) - 1] = '\0'; /* sanity */
/*
* Look for the "Content-length: " header.
*/
#define CONTENTLEN "Content-Length: "
for (cp = buf; *cp != '\0'; cp++) {
if (tolower((unsigned char)*cp) == 'c' &&
strncasecmp(cp, CONTENTLEN, sizeof(CONTENTLEN) - 1) == 0)
break;
}
if (*cp != '\0') {
cp += sizeof(CONTENTLEN) - 1;
ep = strchr(cp, '\n');
if (ep == NULL)
goto improper;
else
*ep = '\0';
filesize = strtoll(cp, &ep, 10);
if (filesize < 1 || *ep != '\0')
goto improper;
} else
filesize = -1;
/* Open the output file. */
out = open(savefile, O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (out < 0) {
warn("Can't open %s", savefile);
goto cleanup_url_get;
}
/* Trap signals */
oldintr = NULL;
if (setjmp(httpabort)) {
if (oldintr)
(void)signal(SIGINT, oldintr);
goto cleanup_url_get;
}
oldintr = signal(SIGINT, aborthttp);
bytes = 0;
hashbytes = mark;
progressmeter(-1);
/* Finally, suck down the file. */
i = 0;
while ((len = read(s, buf, sizeof(buf))) > 0) {
bytes += len;
for (cp = buf; len > 0; len -= i, cp += i) {
if ((i = write(out, cp, len)) == -1) {
warn("Writing %s", savefile);
goto cleanup_url_get;
}
else if (i == 0)
break;
}
if (hash && !progress) {
while (bytes >= hashbytes) {
(void)putchar('#');
hashbytes += mark;
}
(void)fflush(stdout);
}
}
if (hash && !progress && bytes > 0) {
if (bytes < mark)
(void)putchar('#');
(void)putchar('\n');
(void)fflush(stdout);
}
if (len != 0) {
warn("Reading from socket");
goto cleanup_url_get;
}
progressmeter(1);
if (verbose)
puts("Successfully retrieved file.");
(void)signal(SIGINT, oldintr);
close(s);
close(out);
if (proxy)
free(proxy);
free(line);
return (0);
noftpautologin:
warnx(
"Auto-login using ftp URLs isn't supported when using $ftp_proxy");
goto cleanup_url_get;
improper:
warnx("Improper response from %s", host);
cleanup_url_get:
if (s != -1)
close(s);
if (proxy)
free(proxy);
free(line);
if (res0 != NULL)
freeaddrinfo(res0);
return (-1);
}
/*
* Abort a http retrieval
*/
void
aborthttp(notused)
int notused;
{
alarmtimer(0);
puts("\nhttp fetch aborted.");
(void)fflush(stdout);
longjmp(httpabort, 1);
}
/*
* Retrieve multiple files from the command line, transferring
* files of the form "host:path", "ftp://host/path" using the
* ftp protocol, and files of the form "http://host/path" using
* the http protocol.
* If path has a trailing "/", then return (-1);
* 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(argc, argv)
int argc;
char *argv[];
{
static char lasthost[MAXHOSTNAMELEN];
char *xargv[5];
char *cp, *line, *host, *dir, *file, *portnum;
char *user, *pass;
char *ftpproxy, *httpproxy;
int rval, xargc;
volatile int argpos;
int dirhasglob, filehasglob;
char rempath[MAXPATHLEN];
argpos = 0;
if (setjmp(toplevel)) {
if (connected)
disconnect(0, NULL);
return (argpos + 1);
}
(void)signal(SIGINT, (sig_t)intr);
(void)signal(SIGPIPE, (sig_t)lostpeer);
ftpproxy = getenv(FTP_PROXY);
httpproxy = getenv(HTTP_PROXY);
/*
* Loop through as long as there's files to fetch.
*/
for (rval = 0; (rval == 0) && (argpos < argc); free(line), argpos++) {
if (strchr(argv[argpos], ':') == NULL)
break;
host = dir = file = portnum = user = pass = NULL;
/*
* We muck with the string, so we make a copy.
*/
line = strdup(argv[argpos]);
if (line == NULL)
errx(1, "Can't allocate memory for auto-fetch.");
/*
* Try HTTP URL-style arguments first.
*/
if (strncasecmp(line, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
if (url_get(line, httpproxy) == -1)
rval = argpos + 1;
continue;
}
/*
* Try FTP URL-style arguments next. If ftpproxy is
* set, use url_get() instead of standard ftp.
* Finally, try host:file.
*/
host = line;
if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
if (ftpproxy) {
if (url_get(line, ftpproxy) == -1)
rval = argpos + 1;
continue;
}
host += sizeof(FTP_URL) - 1;
dir = strchr(host, '/');
/* look for [user:pass@]host[:port] */
pass = strpbrk(host, ":@/");
if (pass == NULL || *pass == '/') {
pass = NULL;
goto parsed_url;
}
if (pass == host || *pass == '@') {
bad_ftp_url:
warnx("Invalid URL: %s", argv[argpos]);
rval = argpos + 1;
continue;
}
*pass++ = '\0';
cp = strpbrk(pass, ":@/");
if (cp == NULL || *cp == '/') {
portnum = pass;
pass = NULL;
goto parsed_url;
}
if (EMPTYSTRING(cp) || *cp == ':')
goto bad_ftp_url;
*cp++ = '\0';
user = host;
if (EMPTYSTRING(user))
goto bad_ftp_url;
host = cp;
portnum = strchr(host, ':');
if (portnum != NULL)
*portnum++ = '\0';
} else { /* classic style `host:file' */
char *end_brace;
if (*host == '[' &&
(end_brace = strrchr(host, ']')) != NULL) {
/*IPv6 addr in []*/
host++;
*end_brace = '\0';
dir = strchr(end_brace + 1, ':');
} else
dir = strchr(host, ':');
}
parsed_url:
if (EMPTYSTRING(host)) {
rval = argpos + 1;
continue;
}
/*
* If dir is NULL, the file wasn't specified
* (URL looked something like ftp://host)
*/
if (dir != NULL)
*dir++ = '\0';
/*
* Extract the file and (if present) directory name.
*/
if (! EMPTYSTRING(dir)) {
cp = strrchr(dir, '/');
if (cp != NULL) {
*cp++ = '\0';
file = cp;
} else {
file = dir;
dir = NULL;
}
}
if (debug)
printf("user %s:%s host %s port %s dir %s file %s\n",
user, pass, host, portnum, dir, file);
/*
* Set up the connection if we don't have one.
*/
if (strcmp(host, lasthost) != 0) {
int oautologin;
(void)strcpy(lasthost, host);
if (connected)
disconnect(0, NULL);
xargv[0] = __progname;
xargv[1] = host;
xargv[2] = NULL;
xargc = 2;
if (! EMPTYSTRING(portnum)) {
xargv[2] = portnum;
xargv[3] = NULL;
xargc = 3;
}
oautologin = autologin;
if (user != NULL)
autologin = 0;
setpeer(xargc, xargv);
autologin = oautologin;
if ((connected == 0)
|| ((connected == 1) && !login(host, user, pass)) ) {
warnx("Can't connect or login to host `%s'",
host);
rval = argpos + 1;
continue;
}
/* Always use binary transfers. */
setbinary(0, NULL);
}
/* cd back to '/' */
xargv[0] = "cd";
xargv[1] = "/";
xargv[2] = NULL;
cd(2, xargv);
if (! dirchange) {
rval = argpos + 1;
continue;
}
dirhasglob = filehasglob = 0;
if (doglob) {
if (! EMPTYSTRING(dir) &&
strpbrk(dir, "*?[]{}") != NULL)
dirhasglob = 1;
if (! EMPTYSTRING(file) &&
strpbrk(file, "*?[]{}") != NULL)
filehasglob = 1;
}
/* Change directories, if necessary. */
if (! EMPTYSTRING(dir) && !dirhasglob) {
xargv[0] = "cd";
xargv[1] = dir;
xargv[2] = NULL;
cd(2, xargv);
if (! dirchange) {
rval = argpos + 1;
continue;
}
}
if (EMPTYSTRING(file)) {
rval = -1;
continue;
}
if (!verbose)
printf("Retrieving %s/%s\n", dir ? dir : "", file);
if (dirhasglob) {
snprintf(rempath, sizeof(rempath), "%s/%s", dir, file);
file = rempath;
}
/* Fetch the file(s). */
xargv[0] = "get";
xargv[1] = file;
xargv[2] = NULL;
if (dirhasglob || filehasglob) {
int ointeractive;
ointeractive = interactive;
interactive = 0;
xargv[0] = "mget";
mget(2, xargv);
interactive = ointeractive;
} else
get(2, xargv);
if ((code / 100) != COMPLETE)
rval = argpos + 1;
}
if (connected && rval != -1)
disconnect(0, NULL);
return (rval);
}
int
isurl(p)
const char *p;
{
char *path, pton_buf[16];
if (strncasecmp(p, FTP_URL, sizeof(FTP_URL) - 1) == 0
|| strncasecmp(p, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
return 1;
}
if (*p == '[' && (path = strrchr(p, ']')) != NULL) /*IPv6 addr in []*/
return (*(++path) == ':') ? 1 : 0;
#ifdef INET6
if (inet_pton(AF_INET6, p, pton_buf) == 1) /* raw IPv6 addr */
return 0;
#endif
if (strchr(p, ':') != NULL) /* else, if ':' exist */
return 1;
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,189 +0,0 @@
/* $FreeBSD$ */
/* $NetBSD: ftp_var.h,v 1.20.2.1 1997/11/18 01:01:37 mellon Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)ftp_var.h 8.4 (Berkeley) 10/9/94
*/
/*
* FTP global variables.
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <setjmp.h>
#include <stringlist.h>
#include <netinet/in.h>
#include <netdb.h>
#ifndef SMALL
#include <histedit.h>
#endif /* !SMALL */
#include "extern.h"
#define HASHBYTES 1024
#define FTPBUFLEN MAXPATHLEN + 200
#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */
#define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */
#define HTTP_PORT 80 /* default if ! getservbyname("http/tcp") */
#ifndef GATE_PORT
#define GATE_PORT 21 /* default if ! getservbyname("ftpgate/tcp") */
#endif
#ifndef GATE_SERVER
#define GATE_SERVER "" /* default server */
#endif
#define PAGER "more" /* default pager if $PAGER isn't set */
/*
* Options and other state info.
*/
int trace; /* trace packets exchanged */
int hash; /* print # for each buffer transferred */
int mark; /* number of bytes between hashes */
int sendport; /* use PORT cmd for each data connection */
int verbose; /* print messages coming back from server */
int connected; /* 1 = connected to server, -1 = logged in */
int fromatty; /* input is from a terminal */
int interactive; /* interactively prompt on m* cmds */
int confirmrest; /* confirm rest of current m* cmd */
int debug; /* debugging level */
int bell; /* ring bell on cmd completion */
int doglob; /* glob local file names */
int autologin; /* establish user account on connection */
int proxy; /* proxy server connection active */
int proxflag; /* proxy connection exists */
int gatemode; /* use gate-ftp */
char *gateserver; /* server to use for gate-ftp */
int sunique; /* store files on server with unique name */
int runique; /* store local files with unique name */
int mcase; /* map upper to lower case for mget names */
int ntflag; /* use ntin ntout tables for name translation */
int mapflag; /* use mapin mapout templates on file names */
int preserve; /* preserve modification time on files */
int progress; /* display transfer progress bar */
int code; /* return/reply code for ftp command */
int crflag; /* if 1, strip car. rets. on ascii gets */
char pasv[BUFSIZ]; /* passive port for proxy data connection */
int passivemode; /* passive mode enabled */
int restricted_data_ports; /* enable quarantine FTP area */
char *altarg; /* argv[1] with no shell-like preprocessing */
char ntin[17]; /* input translation table */
char ntout[17]; /* output translation table */
char mapin[MAXPATHLEN]; /* input map template */
char mapout[MAXPATHLEN]; /* output map template */
char typename[32]; /* name of file transfer type */
int type; /* requested file transfer type */
int curtype; /* current file transfer type */
char structname[32]; /* name of file transfer structure */
int stru; /* file transfer structure */
char formname[32]; /* name of file transfer format */
int form; /* file transfer format */
char modename[32]; /* name of file transfer mode */
int mode; /* file transfer mode */
char bytename[32]; /* local byte size in ascii */
int bytesize; /* local byte size in binary */
int anonftp; /* automatic anonymous login */
int dirchange; /* remote directory changed by cd command */
int ttywidth; /* width of tty */
char *tmpdir; /* temporary directory */
int try_epsv; /* try EPSV for this session */
#ifndef SMALL
int editing; /* command line editing enabled */
EditLine *el; /* editline(3) status structure */
History *hist; /* editline(3) history structure */
HistEvent he; /* editline(3) history structure */
char *cursor_pos; /* cursor position we're looking for */
size_t cursor_argc; /* location of cursor in margv */
size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */
#endif /* !SMALL */
off_t bytes; /* current # of bytes read */
off_t filesize; /* size of file being transferred */
char *direction; /* direction transfer is occurring */
off_t restart_point; /* offset to restart transfer */
char *hostname; /* name of host connected to */
int unix_server; /* server is unix, can use binary for ascii */
int unix_proxy; /* proxy is unix, can use binary for ascii */
char *ftpport; /* port number to use for ftp connections */
char *httpport; /* port number to use for http connections */
char *gateport; /* port number to use for gateftp connections */
int dobind; /* bind to specific address */
struct addrinfo * bindres0; /* addrinfo for address to bind to */
jmp_buf toplevel; /* non-local goto stuff for cmd scanner */
char line[FTPBUFLEN]; /* input line buffer */
char *stringbase; /* current scan point in line buffer */
char argbuf[FTPBUFLEN]; /* argument storage buffer */
char *argbase; /* current storage point in arg buffer */
StringList *marg_sl; /* stringlist containing margv */
int margc; /* count of arguments on input line */
#define margv (marg_sl->sl_str) /* args parsed from input line */
int cpend; /* flag: if != 0, then pending server reply */
int mflag; /* flag: if != 0, then active multi command */
int options; /* used during socket creation */
/*
* Format of command table.
*/
struct cmd {
char *c_name; /* name of command */
char *c_help; /* help string */
char c_bell; /* give bell when command completes */
char c_conn; /* must be connected to use command */
char c_proxy; /* proxy server may execute */
#ifndef SMALL
char *c_complete; /* context sensitive completion list */
#endif /* !SMALL */
void (*c_handler) __P((int, char **)); /* function to call */
};
struct macel {
char mac_name[9]; /* macro name */
char *mac_start; /* start of macro in macbuf */
char *mac_end; /* end of macro in macbuf */
};
int macnum; /* number of defined macros */
struct macel macros[16];
char macbuf[4096];

View File

@ -1,711 +0,0 @@
/* $NetBSD: main.c,v 1.26 1997/10/14 16:31:22 christos Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\
\tThe Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94";
#else
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: main.c,v 1.26 1997/10/14 16:31:22 christos Exp $");
#endif
#endif /* not lint */
/*
* FTP User Program -- Command Interface.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <locale.h>
#include <netdb.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ftp_var.h"
#include "pathnames.h"
int family = AF_UNSPEC;
int main __P((int, char **));
int
main(argc, argv)
int argc;
char *argv[];
{
int ch, top, rval;
struct passwd *pw = NULL;
char *cp, homedir[MAXPATHLEN], *s;
int dumbterm;
char *src_addr = NULL;
(void) setlocale(LC_ALL, "");
ftpport = "ftp";
httpport = "http";
gateport = NULL;
cp = getenv("FTPSERVERPORT");
if (cp != NULL)
asprintf(&gateport, "%s", cp);
if (!gateport)
asprintf(&gateport, "ftpgate");
doglob = 1;
interactive = 1;
autologin = 1;
passivemode = 0;
restricted_data_ports = 1;
preserve = 1;
verbose = 0;
progress = 0;
gatemode = 0;
#ifndef SMALL
editing = 0;
el = NULL;
hist = NULL;
#endif
mark = HASHBYTES;
marg_sl = sl_init();
if ((tmpdir = getenv("TMPDIR")) == NULL)
tmpdir = _PATH_TMP;
cp = strrchr(argv[0], '/');
cp = (cp == NULL) ? argv[0] : cp + 1;
if ((s = getenv("FTP_PASSIVE_MODE")) != NULL
&& strcasecmp(s, "no") != 0)
passivemode = 1;
if (strcmp(cp, "pftp") == 0)
passivemode = 1;
else if (strcmp(cp, "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));
if (fromatty) {
verbose = 1; /* verbose if from a tty */
#ifndef SMALL
if (! dumbterm)
editing = 1; /* editing mode on if tty is usable */
#endif
}
if (isatty(fileno(stdout)) && !dumbterm)
progress = 1; /* progress bar on if tty is usable */
while ((ch = getopt(argc, argv, "46adeginpP:s:tUvV")) != -1) {
switch (ch) {
case '4':
family = AF_INET;
break;
#ifdef INET6
case '6':
family = AF_INET6;
break;
#endif
case 'a':
anonftp = 1;
break;
case 'd':
options |= SO_DEBUG;
debug++;
break;
case 'e':
#ifndef SMALL
editing = 0;
#endif
break;
case 'g':
doglob = 0;
break;
case 'i':
interactive = 0;
break;
case 'n':
autologin = 0;
break;
case 'p':
passivemode = 1;
break;
case 'P':
ftpport = optarg;
break;
case 's':
dobind = 1;
src_addr = optarg;
break;
case 't':
trace = 1;
break;
case 'U':
restricted_data_ports = 0;
break;
case 'v':
verbose = 1;
break;
case 'V':
verbose = 0;
break;
default:
usage();
}
}
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 (dobind) {
struct addrinfo hints;
struct addrinfo *res;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(src_addr, NULL, &hints, &res);
if (error) {
warnx("%s: %s", src_addr, gai_strerror(error));
if (error == EAI_SYSTEM)
warnx("%s", strerror(errno));
exit(1);
}
bindres0 = res;
}
/*
* Set up the home directory in case we're globbing.
*/
cp = getlogin();
if (cp != NULL) {
pw = getpwnam(cp);
}
if (pw == NULL)
pw = getpwuid(getuid());
if (pw != NULL) {
home = homedir;
(void)strcpy(home, pw->pw_dir);
}
setttywidth(0);
(void)signal(SIGWINCH, setttywidth);
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */
(void)&argc;
(void)&argv;
#endif
if (argc > 0) {
if (strchr(argv[0], ':') != NULL && ! isipv6addr(argv[0])) {
anonftp = 1; /* Handle "automatic" transfers. */
rval = auto_fetch(argc, argv);
if (rval >= 0) /* -1 == connected and cd-ed */
exit(rval);
} else {
char *xargv[4], **xargp = xargv;
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */
(void)&xargp;
#endif
if (setjmp(toplevel))
exit(0);
(void)signal(SIGINT, (sig_t)intr);
(void)signal(SIGPIPE, (sig_t)lostpeer);
*xargp++ = __progname;
*xargp++ = argv[0]; /* host */
if (argc > 1)
*xargp++ = argv[1]; /* port */
*xargp = NULL;
setpeer(xargp-xargv, xargv);
}
}
#ifndef SMALL
controlediting();
#endif /* !SMALL */
top = setjmp(toplevel) == 0;
if (top) {
(void)signal(SIGINT, (sig_t)intr);
(void)signal(SIGPIPE, (sig_t)lostpeer);
}
for (;;) {
cmdscanner(top);
top = 1;
}
}
void
intr()
{
alarmtimer(0);
longjmp(toplevel, 1);
}
void
lostpeer()
{
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);
}
/*
* Generate a prompt
*/
char *
prompt()
{
return ("ftp> ");
}
/*
* Command parser.
*/
void
cmdscanner(top)
int top;
{
struct cmd *c;
int num;
if (!top
#ifndef SMALL
&& !editing
#endif /* !SMALL */
)
(void)putchar('\n');
for (;;) {
#ifndef SMALL
if (!editing) {
#endif /* !SMALL */
if (fromatty)
fputs(prompt(), stdout);
(void)fflush(stdout);
if (fgets(line, sizeof(line), stdin) == NULL)
quit(0, 0);
num = strlen(line);
if (num == 0)
break;
if (line[--num] == '\n') {
if (num == 0)
break;
line[num] = '\0';
} else if (num == sizeof(line) - 2) {
puts("sorry, input line too long.");
while ((num = getchar()) != '\n' && num != EOF)
/* void */;
break;
} /* else it was a line without a newline */
#ifndef SMALL
} else {
const char *buf;
cursor_pos = NULL;
if ((buf = el_gets(el, &num)) == NULL || num == 0)
quit(0, 0);
if (buf[--num] == '\n') {
if (num == 0)
break;
} else if (num >= sizeof(line)) {
puts("sorry, input line too long.");
break;
}
memcpy(line, buf, num);
line[num] = '\0';
history(hist, &he, H_ENTER, buf);
}
#endif /* !SMALL */
makeargv();
if (margc == 0)
continue;
#if 0 && !defined(SMALL) /* XXX: don't want el_parse */
/*
* el_parse returns -1 to signal that it's not been handled
* internally.
*/
if (el_parse(el, margc, margv) != -1)
continue;
#endif /* !SMALL */
c = getcmd(margv[0]);
if (c == (struct cmd *)-1) {
puts("?Ambiguous command.");
continue;
}
if (c == 0) {
puts("?Invalid command.");
continue;
}
if (c->c_conn && !connected) {
puts("Not connected.");
continue;
}
confirmrest = 0;
(*c->c_handler)(margc, margv);
if (bell && c->c_bell)
(void)putchar('\007');
if (c->c_handler != help)
break;
}
(void)signal(SIGINT, (sig_t)intr);
(void)signal(SIGPIPE, (sig_t)lostpeer);
}
struct cmd *
getcmd(name)
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()
{
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();
sl_add(marg_sl, argp);
if (argp == NULL)
break;
}
#ifndef SMALL
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 /* !SMALL */
}
#ifdef SMALL
#define INC_CHKCURSOR(x) (x)++
#else /* !SMALL */
#define INC_CHKCURSOR(x) { (x)++ ; \
if (x == cursor_pos) { \
cursor_argc = margc; \
cursor_argo = ap-argbase; \
cursor_pos = NULL; \
} }
#endif /* !SMALL */
/*
* Parse string into argbuf;
* implemented with FSM to
* handle quoting and strings
*/
char *
slurpstring()
{
int got_one = 0;
char *sb = stringbase;
char *ap = argbase;
char *tmp = argbase; /* will return this if token found */
if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */
switch (slrflag) { /* and $ as token for macro invoke */
case 0:
slrflag++;
INC_CHKCURSOR(stringbase);
return ((*sb == '!') ? "!" : "$");
/* NOTREACHED */
case 1:
slrflag++;
altarg = stringbase;
break;
default:
break;
}
}
S0:
switch (*sb) {
case '\0':
goto OUT;
case ' ':
case '\t':
INC_CHKCURSOR(sb);
goto S0;
default:
switch (slrflag) {
case 0:
slrflag++;
break;
case 1:
slrflag++;
altarg = sb;
break;
default:
break;
}
goto S1;
}
S1:
switch (*sb) {
case ' ':
case '\t':
case '\0':
goto OUT; /* end of token */
case '\\':
INC_CHKCURSOR(sb);
goto S2; /* slurp next character */
case '"':
INC_CHKCURSOR(sb);
goto S3; /* slurp quoted string */
default:
*ap = *sb; /* add character to token */
ap++;
INC_CHKCURSOR(sb);
got_one = 1;
goto S1;
}
S2:
switch (*sb) {
case '\0':
goto OUT;
default:
*ap = *sb;
ap++;
INC_CHKCURSOR(sb);
got_one = 1;
goto S1;
}
S3:
switch (*sb) {
case '\0':
goto OUT;
case '"':
INC_CHKCURSOR(sb);
goto S1;
default:
*ap = *sb;
ap++;
INC_CHKCURSOR(sb);
got_one = 1;
goto S3;
}
OUT:
if (got_one)
*ap++ = '\0';
argbase = ap; /* update storage pointer */
stringbase = sb; /* update scan pointer */
if (got_one) {
return (tmp);
}
switch (slrflag) {
case 0:
slrflag++;
break;
case 1:
slrflag++;
altarg = (char *) 0;
break;
default:
break;
}
return ((char *)0);
}
/*
* Help command.
* Call each command handler with argc == 0 and argv[0] == name.
*/
void
help(argc, argv)
int argc;
char *argv[];
{
struct cmd *c;
if (argc == 1) {
StringList *buf;
buf = sl_init();
printf("%sommands may be abbreviated. Commands are:\n\n",
proxy ? "Proxy c" : "C");
for (c = cmdtab; c < &cmdtab[NCMDS]; c++)
if (c->c_name && (!proxy || c->c_proxy))
sl_add(buf, c->c_name);
list_vertical(buf);
sl_free(buf, 0);
return;
}
#define HELPINDENT ((int) sizeof("disconnect"))
while (--argc > 0) {
char *arg;
arg = *++argv;
c = getcmd(arg);
if (c == (struct cmd *)-1)
printf("?Ambiguous help command %s\n", arg);
else if (c == (struct cmd *)0)
printf("?Invalid help command %s\n", arg);
else
printf("%-*s\t%s\n", HELPINDENT,
c->c_name, c->c_help);
}
}
void
usage()
{
(void)fprintf(stderr,
"usage: %s [-46adeginptUvV] [-P port] [-s src_addr] [host [port]]\n"
" %s host:path[/]\n"
" %s ftp://host[:port]/path[/]\n"
" %s http://host[:port]/file\n",
__progname, __progname, __progname, __progname);
exit(1);
}

View File

@ -1,41 +0,0 @@
/* $FreeBSD$ */
/* $NetBSD: pathnames.h,v 1.7 1997/01/09 20:19:40 tls Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/
#include <paths.h>
#define TMPFILE "ftpXXXXXX"

View File

@ -1,306 +0,0 @@
/* $NetBSD: ruserpass.c,v 1.14.2.1 1997/11/18 01:02:05 mellon 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95";
#else
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: ruserpass.c,v 1.14.2.1 1997/11/18 01:02:05 mellon Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "ftp_var.h"
static int token __P((void));
static FILE *cfile;
#define DEFAULT 1
#define LOGIN 2
#define PASSWD 3
#define ACCOUNT 4
#define MACDEF 5
#define ID 10
#define MACH 11
static char tokval[100];
static struct toktab {
char *tokstr;
int tval;
} toktab[]= {
{ "default", DEFAULT },
{ "login", LOGIN },
{ "password", PASSWD },
{ "passwd", PASSWD },
{ "account", ACCOUNT },
{ "machine", MACH },
{ "macdef", MACDEF },
{ NULL, 0 }
};
int
ruserpass(host, aname, apass, aacct)
const char *host;
char **aname, **apass, **aacct;
{
char *hdir, buf[BUFSIZ], *tmp;
char myname[MAXHOSTNAMELEN], *mydomain;
int t, i, c, usedefault = 0;
struct stat stb;
hdir = getenv("HOME");
if (hdir == NULL)
hdir = ".";
if (strlen(hdir) + sizeof(".netrc") < sizeof(buf)) {
(void)snprintf(buf, sizeof buf, "%s/.netrc", hdir);
} else {
warnx("%s/.netrc: %s", hdir, strerror(ENAMETOOLONG));
return (0);
}
cfile = fopen(buf, "r");
if (cfile == NULL) {
if (errno != ENOENT)
warn("%s", buf);
return (0);
}
if (gethostname(myname, sizeof(myname)) < 0)
myname[0] = '\0';
if ((mydomain = strchr(myname, '.')) == NULL)
mydomain = "";
next:
while ((t = token())) switch(t) {
case DEFAULT:
usedefault = 1;
/* FALL THROUGH */
case MACH:
if (!usedefault) {
if (token() != ID)
continue;
/*
* Allow match either for user's input host name
* or official hostname. Also allow match of
* incompletely-specified host in local domain.
*/
if (strcasecmp(host, tokval) == 0)
goto match;
if (strcasecmp(hostname, tokval) == 0)
goto match;
if ((tmp = strchr(hostname, '.')) != NULL &&
strcasecmp(tmp, mydomain) == 0 &&
strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
tokval[tmp - hostname] == '\0')
goto match;
if ((tmp = strchr(host, '.')) != NULL &&
strcasecmp(tmp, mydomain) == 0 &&
strncasecmp(host, tokval, tmp - host) == 0 &&
tokval[tmp - host] == '\0')
goto match;
continue;
}
match:
while ((t = token()) && t != MACH && t != DEFAULT) switch(t) {
case LOGIN:
if (token()) {
if (*aname == NULL) {
*aname = strdup(tokval);
if (*aname == NULL)
err(1, "can't strdup *aname");
} else {
if (strcmp(*aname, tokval))
goto next;
}
}
break;
case PASSWD:
if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
fstat(fileno(cfile), &stb) >= 0 &&
(stb.st_mode & 077) != 0) {
warnx("Error: .netrc file is readable by others.");
warnx("Remove password or make file unreadable by others.");
goto bad;
}
if (token() && *apass == NULL) {
*apass = strdup(tokval);
if (*apass == NULL)
err(1, "can't strdup *apass");
}
break;
case ACCOUNT:
if (fstat(fileno(cfile), &stb) >= 0
&& (stb.st_mode & 077) != 0) {
warnx("Error: .netrc file is readable by others.");
warnx("Remove account or make file unreadable by others.");
goto bad;
}
if (token() && *aacct == NULL) {
*aacct = strdup(tokval);
if (*aacct == NULL)
err(1, "can't strdup *aacct");
}
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') {
puts("Missing macdef name argument.");
goto bad;
}
if (macnum == 16) {
puts(
"Limit of 16 macros have already been defined.");
goto bad;
}
tmp = macros[macnum].mac_name;
*tmp++ = c;
for (i=0; i < 8 && (c=getc(cfile)) != EOF &&
(!isascii(c) || !isspace(c)); ++i) {
*tmp++ = c;
}
if (c == EOF) {
puts(
"Macro definition missing null line terminator.");
goto bad;
}
*tmp = '\0';
if (c != '\n') {
while ((c=getc(cfile)) != EOF && c != '\n');
}
if (c == EOF) {
puts(
"Macro definition missing null line terminator.");
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) {
puts(
"Macro definition missing null line terminator.");
goto bad;
}
*tmp = c;
if (*tmp == '\n') {
if (*(tmp-1) == '\0') {
macros[macnum++].mac_end = tmp - 1;
break;
}
*tmp = '\0';
}
tmp++;
}
if (tmp == macbuf + 4096) {
puts("4K macro buffer exceeded.");
goto bad;
}
break;
default:
warnx("Unknown .netrc keyword %s", tokval);
break;
}
goto done;
}
done:
(void)fclose(cfile);
return (0);
bad:
(void)fclose(cfile);
return (-1);
}
static int
token()
{
char *cp;
int c;
struct toktab *t;
if (feof(cfile) || ferror(cfile))
return (0);
while ((c = getc(cfile)) != EOF &&
(c == '\n' || c == '\t' || c == ' ' || c == ','))
continue;
if (c == EOF)
return (0);
cp = tokval;
if (c == '"') {
while ((c = getc(cfile)) != EOF && c != '"') {
if (c == '\\')
c = getc(cfile);
*cp++ = c;
}
} else {
*cp++ = c;
while ((c = getc(cfile)) != EOF
&& c != '\n' && c != '\t' && c != ' ' && c != ',') {
if (c == '\\')
c = getc(cfile);
*cp++ = c;
}
}
*cp = 0;
if (tokval[0] == 0)
return (0);
for (t = toktab; t->tokstr; t++)
if (!strcmp(t->tokstr, tokval))
return (t->tval);
return (ID);
}

View File

@ -1,897 +0,0 @@
/* $NetBSD: util.c,v 1.16.2.1 1997/11/18 01:02:33 mellon Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$FreeBSD$");
__RCSID_SOURCE("$NetBSD: util.c,v 1.16.2.1 1997/11/18 01:02:33 mellon Exp $");
#endif /* not lint */
/*
* FTP User Program -- Misc support routines
*/
#include <sys/ioctl.h>
#include <sys/time.h>
#include <arpa/ftp.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <glob.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#ifdef INET6
#include <netdb.h>
#endif
#include "ftp_var.h"
#include "pathnames.h"
#ifndef SECSPERHOUR
#define SECSPERHOUR (60*60)
#endif
/*
* Connect to peer server and
* auto-login, if possible.
*/
void
setpeer(argc, argv)
int argc;
char *argv[];
{
char *host;
char *port;
if (connected) {
printf("Already connected to %s, use close first.\n",
hostname);
code = -1;
return;
}
if (argc < 2)
(void)another(&argc, &argv, "to");
if (argc < 2 || argc > 3) {
printf("usage: %s host-name [port]\n", argv[0]);
code = -1;
return;
}
if (gatemode)
port = gateport;
else
port = ftpport;
if (argc > 2)
port = strdup(argv[2]);
if (gatemode) {
if (gateserver == NULL || *gateserver == '\0')
errx(1, "gateserver not defined (shouldn't happen)");
host = hookup(gateserver, port);
} else
host = hookup(argv[1], port);
if (host) {
int overbose;
if (gatemode) {
if (command("PASSERVE %s", argv[1]) != COMPLETE)
return;
if (verbose)
printf("Connected via pass-through server %s\n",
gateserver);
}
connected = 1;
try_epsv = 1;
/*
* Set up defaults for FTP.
*/
(void)strcpy(typename, "ascii"), type = TYPE_A;
curtype = TYPE_A;
(void)strcpy(formname, "non-print"), form = FORM_N;
(void)strcpy(modename, "stream"), mode = MODE_S;
(void)strcpy(structname, "file"), stru = STRU_F;
(void)strcpy(bytename, "8"), bytesize = 8;
if (autologin)
(void)login(argv[1], NULL, NULL);
overbose = verbose;
if (debug == 0)
verbose = -1;
if (command("SYST") == COMPLETE && overbose) {
char *cp, c;
c = 0;
cp = strchr(reply_string+4, ' ');
if (cp == NULL)
cp = strchr(reply_string+4, '\r');
if (cp) {
if (cp[-1] == '.')
cp--;
c = *cp;
*cp = '\0';
}
printf("Remote system type is %s.\n", reply_string + 4);
if (cp)
*cp = c;
}
if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
if (proxy)
unix_proxy = 1;
else
unix_server = 1;
/*
* Set type to 0 (not specified by user),
* meaning binary by default, but don't bother
* telling server. We can use binary
* for text files unless changed by the user.
*/
type = 0;
(void)strcpy(typename, "binary");
if (overbose)
printf("Using %s mode to transfer files.\n",
typename);
} else {
if (proxy)
unix_proxy = 0;
else
unix_server = 0;
if (overbose &&
!strncmp(reply_string, "215 TOPS20", 10))
puts(
"Remember to set tenex mode when transferring binary files from this machine.");
}
verbose = overbose;
}
}
/*
* login to remote host, using given username & password if supplied
*/
int
login(host, user, pass)
const char *host;
char *user, *pass;
{
char tmp[80];
char *acct;
char anonpass[MAXLOGNAME + 1 + MAXHOSTNAMELEN]; /* "user@hostname" */
char hostname[MAXHOSTNAMELEN];
struct passwd *pw;
int n, aflag = 0;
acct = NULL;
if (user == NULL) {
if (ruserpass(host, &user, &pass, &acct) < 0) {
code = -1;
return (0);
}
}
/*
* Set up arguments for an anonymous FTP session, if necessary.
*/
if ((user == NULL || pass == NULL) && anonftp) {
memset(anonpass, 0, sizeof(anonpass));
memset(hostname, 0, sizeof(hostname));
/*
* Set up anonymous login password.
*/
if ((user = getlogin()) == NULL) {
if ((pw = getpwuid(getuid())) == NULL)
user = "anonymous";
else
user = pw->pw_name;
}
gethostname(hostname, MAXHOSTNAMELEN);
#ifndef DONT_CHEAT_ANONPASS
/*
* 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
*/
snprintf(anonpass, sizeof(anonpass) - 1, "%s@",
user);
#else
snprintf(anonpass, sizeof(anonpass) - 1, "%s@%s",
user, hp->h_name);
#endif
pass = anonpass;
user = "anonymous"; /* as per RFC 1635 */
}
while (user == NULL) {
char *myname = getlogin();
if (myname == NULL && (pw = getpwuid(getuid())) != NULL)
myname = pw->pw_name;
if (myname)
printf("Name (%s:%s): ", host, myname);
else
printf("Name (%s): ", host);
(void)fflush(stdout);
if (fgets(tmp, sizeof(tmp) - 1, stdin) == NULL)
return (0);
tmp[strlen(tmp) - 1] = '\0';
if (*tmp == '\0')
user = myname;
else
user = tmp;
}
n = command("USER %s", user);
if (n == CONTINUE) {
if (pass == NULL)
pass = getpass("Password:");
n = command("PASS %s", pass);
}
if (n == CONTINUE) {
aflag++;
if (acct == NULL)
acct = getpass("Account:");
n = command("ACCT %s", acct);
}
if ((n != COMPLETE) ||
(!aflag && acct != NULL && command("ACCT %s", acct) != COMPLETE)) {
warnx("Login failed.");
return (0);
}
if (proxy)
return (1);
connected = -1;
for (n = 0; n < macnum; ++n) {
if (!strcmp("init", macros[n].mac_name)) {
(void)strcpy(line, "$init");
makeargv();
domacro(margc, margv);
break;
}
}
return (1);
}
/*
* `another' gets another argument, and stores the new argc and argv.
* It reverts to the top level (via main.c's intr()) on EOF/error.
*
* Returns false if no new arguments have been added.
*/
int
another(pargc, pargv, prompt)
int *pargc;
char ***pargv;
const char *prompt;
{
int len = strlen(line), ret;
if (len >= sizeof(line) - 3) {
puts("sorry, arguments too long.");
intr();
}
printf("(%s) ", prompt);
line[len++] = ' ';
if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
intr();
len += strlen(&line[len]);
if (len > 0 && line[len - 1] == '\n')
line[len - 1] = '\0';
makeargv();
ret = margc > *pargc;
*pargc = margc;
*pargv = margv;
return (ret);
}
/*
* glob files given in argv[] from the remote server.
* if errbuf isn't NULL, store error messages there instead
* of writing to the screen.
*/
char *
remglob(argv, doswitch, errbuf)
char *argv[];
int doswitch;
char **errbuf;
{
char temp[MAXPATHLEN];
static char buf[MAXPATHLEN];
static FILE *ftemp = NULL;
static char **args;
int oldverbose, oldhash, fd;
char *cp, *mode;
if (!mflag) {
if (!doglob)
args = NULL;
else {
if (ftemp) {
(void)fclose(ftemp);
ftemp = NULL;
}
}
return (NULL);
}
if (!doglob) {
if (args == NULL)
args = argv;
if ((cp = *++args) == NULL)
args = NULL;
return (cp);
}
if (ftemp == NULL) {
(void)snprintf(temp, sizeof(temp), "%s/%s", tmpdir, TMPFILE);
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;
hash = 0;
if (doswitch)
pswitch(!proxy);
for (mode = "w"; *++argv != NULL; mode = "a")
recvrequest("NLST", temp, *argv, mode, 0, 0);
if ((code / 100) != COMPLETE) {
if (errbuf != NULL)
*errbuf = reply_string;
}
if (doswitch)
pswitch(!proxy);
verbose = oldverbose;
hash = oldhash;
ftemp = fopen(temp, "r");
(void)unlink(temp);
if (ftemp == NULL) {
if (errbuf == NULL)
puts("can't find list of remote files, oops.");
else
*errbuf =
"can't find list of remote files, oops.";
return (NULL);
}
}
if (fgets(buf, sizeof(buf), ftemp) == NULL) {
(void)fclose(ftemp);
ftemp = NULL;
return (NULL);
}
if ((cp = strchr(buf, '\n')) != NULL)
*cp = '\0';
return (buf);
}
int
confirm(cmd, file)
const char *cmd, *file;
{
char line[BUFSIZ];
if (!interactive || confirmrest)
return (1);
printf("%s %s? ", cmd, file);
(void)fflush(stdout);
if (fgets(line, sizeof(line), stdin) == NULL)
return (0);
switch (tolower((unsigned char)*line)) {
case 'n':
return (0);
case 'p':
interactive = 0;
puts("Interactive mode: off.");
break;
case 'a':
confirmrest = 1;
printf("Prompting off for duration of %s.\n", cmd);
break;
}
return (1);
}
/*
* Glob a local file name specification with
* the expectation of a single return value.
* Can't control multiple values being expanded
* from the expression, we return only the first.
*/
int
globulize(cpp)
char **cpp;
{
glob_t gl;
int flags;
if (!doglob)
return (1);
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
memset(&gl, 0, sizeof(gl));
if (glob(*cpp, flags, NULL, &gl) ||
gl.gl_pathc == 0) {
warnx("%s: not found", *cpp);
globfree(&gl);
return (0);
}
/* XXX: caller should check if *cpp changed, and
* free(*cpp) if that is the case
*/
*cpp = strdup(gl.gl_pathv[0]);
globfree(&gl);
return (1);
}
/*
* determine size of remote file
*/
off_t
remotesize(file, noisy)
const char *file;
int noisy;
{
int overbose;
off_t size;
overbose = verbose;
size = -1;
if (debug == 0)
verbose = -1;
if (command("SIZE %s", file) == COMPLETE) {
char *cp, *ep;
cp = strchr(reply_string, ' ');
if (cp != NULL) {
cp++;
size = strtoq(cp, &ep, 10);
if (*ep != '\0' && !isspace((unsigned char)*ep))
size = -1;
}
} else if (noisy && debug == 0)
puts(reply_string);
verbose = overbose;
return (size);
}
/*
* determine last modification time (in GMT) of remote file
*/
time_t
remotemodtime(file, noisy)
const char *file;
int noisy;
{
struct tm timebuf;
time_t rtime;
int len, month, ocode, overbose, y2kbug, year;
char *fmt;
char mtbuf[17];
overbose = verbose;
ocode = code;
rtime = -1;
if (debug == 0)
verbose = -1;
if (command("MDTM %s", file) == COMPLETE) {
memset(&timebuf, 0, sizeof(timebuf));
/*
* Parse the time string, which is expected to be 14
* characters long. Some broken servers send tm_year
* formatted with "19%02d", which produces an incorrect
* (but parsable) 15 characters for years >= 2000.
* Scan for invalid trailing junk by accepting up to 16
* characters.
*/
if (sscanf(reply_string, "%*s %16s", mtbuf) == 1) {
fmt = NULL;
len = strlen(mtbuf);
y2kbug = 0;
if (len == 15 && strncmp(mtbuf, "19", 2) == 0) {
fmt = "19%03d%02d%02d%02d%02d%02d";
y2kbug = 1;
} else if (len == 14)
fmt = "%04d%02d%02d%02d%02d%02d";
if (fmt != NULL) {
if (sscanf(mtbuf, fmt, &year, &month,
&timebuf.tm_mday, &timebuf.tm_hour,
&timebuf.tm_min, &timebuf.tm_sec) == 6) {
timebuf.tm_isdst = -1;
timebuf.tm_mon = month - 1;
if (y2kbug)
timebuf.tm_year = year;
else
timebuf.tm_year = year - 1900;
rtime = mktime(&timebuf);
}
}
}
if (rtime == -1) {
if (noisy || debug != 0)
printf("Can't convert %s to a time.\n", mtbuf);
} else
rtime += timebuf.tm_gmtoff; /* conv. local -> GMT */
} else if (noisy && debug == 0)
puts(reply_string);
verbose = overbose;
if (rtime == -1)
code = ocode;
return (rtime);
}
void updateprogressmeter __P((int));
void
updateprogressmeter(dummy)
int dummy;
{
static pid_t pgrp = -1;
int ctty_pgrp;
if (pgrp == -1)
pgrp = getpgrp();
/*
* print progress bar only if we are foreground process.
*/
if (ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
ctty_pgrp == (int)pgrp)
progressmeter(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;
void
progressmeter(flag)
int flag;
{
/*
* List of order of magnitude prefixes.
* The last is `P', as 2^64 = 16384 Petabytes
*/
static const char prefixes[] = " KMGTP";
static struct timeval lastupdate;
static off_t lastsize;
struct timeval now, td, wait;
off_t cursize, abbrevsize;
double elapsed;
int ratio, barlength, i, len, n;
off_t remaining;
char buf[256];
len = 0;
if (flag == -1) {
(void)gettimeofday(&start, (struct timezone *)0);
lastupdate = start;
lastsize = restart_point;
}
(void)gettimeofday(&now, (struct timezone *)0);
if (!progress || filesize <= 0)
return;
cursize = bytes + restart_point;
ratio = cursize * 100 / filesize;
ratio = MAX(ratio, 0);
ratio = MIN(ratio, 100);
n = snprintf(buf + len, sizeof(buf) - len, "\r%3d%% ", ratio);
if (n > 0 && n < sizeof(buf) - len)
len += n;
barlength = ttywidth - 30;
if (barlength > 0) {
if (barlength > 154)
barlength = 154; /* Number of '*'s below */
i = barlength * ratio / 100;
n = snprintf(buf + len, sizeof(buf) - len,
"|%.*s%*s|", i,
"*****************************************************************************"
"*****************************************************************************",
barlength - i, "");
if (n > 0 && n < sizeof(buf) - len)
len += n;
}
i = 0;
abbrevsize = cursize;
while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
i++;
abbrevsize >>= 10;
}
n = snprintf(buf + len, sizeof(buf) - len,
" %5qd %c%c ", (long long)abbrevsize, prefixes[i],
prefixes[i] == ' ' ? ' ' : 'B');
if (n > 0 && n < sizeof(buf) - len)
len += n;
timersub(&now, &lastupdate, &wait);
if (cursize > lastsize) {
lastupdate = now;
lastsize = cursize;
if (wait.tv_sec >= STALLTIME) { /* fudge out stalled time */
start.tv_sec += wait.tv_sec;
start.tv_usec += wait.tv_usec;
}
wait.tv_sec = 0;
}
timersub(&now, &start, &td);
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) {
n = snprintf(buf + len, sizeof(buf) - len,
" --:-- ETA");
} else if (wait.tv_sec >= STALLTIME) {
n = snprintf(buf + len, sizeof(buf) - len,
" - stalled -");
} else {
remaining =
((filesize - restart_point) / (bytes / elapsed) - elapsed);
if (remaining >= 100 * SECSPERHOUR)
n = snprintf(buf + len, sizeof(buf) - len,
" --:-- ETA");
else {
i = remaining / SECSPERHOUR;
if (i)
n = snprintf(buf + len, sizeof(buf) - len,
"%2d:", i);
else
n = snprintf(buf + len, sizeof(buf) - len,
" ");
if (n > 0 && n < sizeof(buf) - len)
len += n;
i = remaining % SECSPERHOUR;
n = snprintf(buf + len, sizeof(buf) - len,
"%02d:%02d ETA", i / 60, i % 60);
}
}
if (n > 0 && n < sizeof(buf) - len)
len += n;
(void)write(STDOUT_FILENO, buf, len);
if (flag == -1) {
(void)signal(SIGALRM, updateprogressmeter);
alarmtimer(1); /* set alarm timer for 1 Hz */
} else if (flag == 1) {
alarmtimer(0);
(void)putchar('\n');
}
fflush(stdout);
}
/*
* 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 STDOUT.
*/
void
ptransfer(siginfo)
int siginfo;
{
struct timeval now, td;
double elapsed;
off_t bs;
int meg, n, remaining, hh, len;
char buf[100];
if (!verbose && !siginfo)
return;
(void)gettimeofday(&now, (struct timezone *)0);
timersub(&now, &start, &td);
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
bs = bytes / (elapsed == 0.0 ? 1 : elapsed);
meg = 0;
if (bs > (1024 * 1024))
meg = 1;
len = 0;
n = snprintf(buf + len, sizeof(buf) - len,
"%qd byte%s %s in %.2f seconds (%.2f %sB/s)\n",
(long long)bytes, bytes == 1 ? "" : "s", direction, elapsed,
bs / (1024.0 * (meg ? 1024.0 : 1.0)), meg ? "M" : "K");
if (n > 0 && n < sizeof(buf) - len)
len += n;
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--; /* decrement len to overwrite \n */
n = snprintf(buf + len, sizeof(buf) - len,
" ETA: %02d:%02d:%02d\n", hh, remaining / 60,
remaining % 60);
if (n > 0 && n < sizeof(buf) - len)
len += n;
}
(void)write(siginfo ? STDERR_FILENO : STDOUT_FILENO, buf, len);
}
/*
* List words in stringlist, vertically arranged
*/
void
list_vertical(sl)
StringList *sl;
{
int i, j, w;
int columns, width, lines, items;
char *p;
width = items = 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, stdout);
if (j * lines + i + lines >= sl->sl_cur) {
putchar('\n');
break;
}
w = strlen(p);
while (w < width) {
w = (w + 8) &~ 7;
(void)putchar('\t');
}
}
}
}
/*
* Update the global ttywidth value, using TIOCGWINSZ.
*/
void
setttywidth(a)
int a;
{
struct winsize winsize;
if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
ttywidth = winsize.ws_col;
else
ttywidth = 80;
}
/*
* Set the SIGALRM interval timer for wait seconds, 0 to disable.
*/
void
alarmtimer(wait)
int wait;
{
struct itimerval itv;
itv.it_value.tv_sec = wait;
itv.it_value.tv_usec = 0;
itv.it_interval = itv.it_value;
setitimer(ITIMER_REAL, &itv, NULL);
}
/*
* Setup or cleanup EditLine structures
*/
#ifndef SMALL
void
controlediting()
{
if (editing && el == NULL && hist == NULL) {
/* init editline */
el = el_init(__progname, stdin, stdout, stderr);
hist = history_init(); /* init the builtin history */
history(hist, &he, H_EVENT, 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 function */
/* 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 */
el_set(el, EL_SIGNAL, 1);
} else if (!editing) {
if (hist) {
history_end(hist);
hist = NULL;
}
if (el) {
el_end(el);
el = NULL;
}
}
}
#endif /* !SMALL */
/*
* Determine if given string is an IPv6 address or not.
* Return 1 for yes, 0 for no
*/
int
isipv6addr(const char *addr)
{
int rv = 0;
#ifdef INET6
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
hints.ai_flags = AI_NUMERICHOST;
if (getaddrinfo(addr, "0", &hints, &res) != 0)
rv = 0;
else {
rv = 1;
freeaddrinfo(res);
}
if (debug)
printf("isipv6addr: got %d for %s\n", rv, addr);
#endif
return (rv == 1) ? 1 : 0;
}