Importing usr.bin/ftp
This commit is contained in:
parent
2db46bcfa1
commit
04203a83a6
37 changed files with 15092 additions and 2982 deletions
|
@ -10,7 +10,7 @@ SUBDIR= add_route arp ash at backup basename btrace \
|
|||
dhrystone diff dirname diskctl dumpcore \
|
||||
eject env expand factor fbdctl \
|
||||
find finger fingerd fix fold format fortune fsck.mfs \
|
||||
ftp101 gcore gcov-pull getty grep hexdump host \
|
||||
gcore gcov-pull getty grep hexdump host \
|
||||
hostaddr id ifconfig ifdef \
|
||||
intr ipcrm ipcs irdpd isoread last \
|
||||
less loadkeys loadramdisk logger look lp \
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
# Makefile for ftp
|
||||
#
|
||||
# 01/25/96 Initial Release Michael Temari
|
||||
# 03/08/00 Michael Temari, <Michael@TemWare.Com>
|
||||
# 02/07/05 v. 1.01 Michael Temari, <Michael@TemWare.Com>
|
||||
|
||||
PROG= ftp
|
||||
SRCS= ftp.c local.c file.c xfer.c other.c net.c crc.c
|
||||
CPPFLAGS+= -DCRC_ONLY
|
||||
|
||||
.include <bsd.prog.mk>
|
|
@ -1,39 +0,0 @@
|
|||
ftp101 --- An FTP client program for Minix 2.0
|
||||
written by Michael Temari <Michael@TemWare.Com> release 1.01a 2006-06-07
|
||||
|
||||
Full download: <a href="/pub/contrib/ftp101.tar.Z">ftp101.tar.Z</a>
|
||||
|
||||
FTP is the File Transfer Protocol client that allows you to connect to
|
||||
a remote FTP server.
|
||||
|
||||
This version should work equally well with Minix 2 and Minix 3.
|
||||
|
||||
Release 1.01a 2006-06-07: minor documentation edits
|
||||
Release 1.01 2005-02-07: minor bug fix
|
||||
Release 1.00 2003-12-14: added "ver" command to display current version
|
||||
and an ftp(1) man page.
|
||||
|
||||
Installation: unpack the tarball, it will create an ftp101 directory. Although
|
||||
this is a replacement for the ftp client provided in the Minix 2.0.0 and later
|
||||
distributions, it is suggested you unpack and compile in the /usr/local/src
|
||||
directory.
|
||||
|
||||
zcat < ftp101.tar.Z | tar xvfp -
|
||||
|
||||
Invoking make -n will show you what the Makefile will do.
|
||||
|
||||
make (or make ftp) compiles a new ftp binary, leaving it in the source
|
||||
directory.
|
||||
|
||||
make install compiles the binary and installs it in /usr/bin.
|
||||
|
||||
make installman installs the man page in /usr/local/man/man1. The
|
||||
directory must exist.
|
||||
|
||||
Note: there is a bug in the version of the ftp client distributed with
|
||||
Minix 2.0.2 and 2.0.3 that causes a \r (0xd) character to be appended
|
||||
to file names in the destination directory when files are downloaded in
|
||||
binary mode using the mget command. The bug was corrected in a release
|
||||
prior to 1.00.
|
||||
|
||||
Notes by ASW revised 2006-06-07
|
|
@ -1,132 +0,0 @@
|
|||
/* Compute checksum Author: Johan W. Stevenson */
|
||||
|
||||
/* Copyright 1988 by Johan W. Stevenson */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !CRC_ONLY
|
||||
|
||||
int errs;
|
||||
|
||||
#if __STDC__
|
||||
int main(int argc, char **argv);
|
||||
void crc(char *fname);
|
||||
#else
|
||||
void crc();
|
||||
#endif
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char line[256];
|
||||
|
||||
if (argc <= 1)
|
||||
crc((char *) 0);
|
||||
else if (argc == 2 && strcmp(argv[1], "-") == 0)
|
||||
while (fgets(line, sizeof line, stdin) != NULL) {
|
||||
if (line[strlen(line) - 1] == '\n')
|
||||
line[strlen(line) - 1] = '\0';
|
||||
crc(line);
|
||||
}
|
||||
else
|
||||
do {
|
||||
crc(argv[1]);
|
||||
argv++;
|
||||
argc--;
|
||||
} while (argc > 1);
|
||||
return(errs != 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Crctab calculated by Mark G. Mendel, Network Systems Corporation */
|
||||
static unsigned short crctab[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
|
||||
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
|
||||
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
|
||||
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
|
||||
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
|
||||
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
|
||||
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
|
||||
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
|
||||
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
|
||||
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
|
||||
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
|
||||
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
|
||||
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
|
||||
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
|
||||
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
|
||||
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
|
||||
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
|
||||
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
|
||||
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
|
||||
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
|
||||
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
|
||||
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
|
||||
};
|
||||
|
||||
/* Updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
|
||||
* NOTE: First argument must be in range 0 to 255.
|
||||
* Second argument is referenced twice.
|
||||
*
|
||||
* Programmers may incorporate any or all code into their programs,
|
||||
* giving proper credit within the source. Publication of the
|
||||
* source routines is permitted so long as proper credit is given
|
||||
* to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
|
||||
* Omen Technology.
|
||||
*/
|
||||
|
||||
#define updcrc(cp, crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ cp)
|
||||
|
||||
#if CRC_ONLY
|
||||
unsigned short crc(char *fname)
|
||||
#else
|
||||
void crc(fname)
|
||||
char *fname;
|
||||
#endif
|
||||
{
|
||||
register int c;
|
||||
register long len = 0;
|
||||
register unsigned short crc = 0;
|
||||
register FILE *fp;
|
||||
|
||||
#if CRC_ONLY
|
||||
if((fp = fopen(fname, "r")) == NULL)
|
||||
return 0;
|
||||
#else
|
||||
if (fname == NULL)
|
||||
fp = stdin;
|
||||
else if ((fp = fopen(fname, "r")) == NULL) {
|
||||
fprintf(stderr, "crc: cannot open %s\n", fname);
|
||||
errs++;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
while ((c = getc(fp)) != EOF) {
|
||||
len++;
|
||||
crc = updcrc(c, crc);
|
||||
}
|
||||
#if CRC_ONLY
|
||||
fclose(fp);
|
||||
return crc;
|
||||
#else
|
||||
printf("%05u %6ld", crc, len);
|
||||
if (fname) {
|
||||
printf(" %s", fname);
|
||||
fclose(fp);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
|
@ -1,935 +0,0 @@
|
|||
/* file.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <utime.h>
|
||||
#include <net/hton.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "file.h"
|
||||
#include "net.h"
|
||||
|
||||
static char *dir(char *path, int full);
|
||||
static int asciisize(int fd, off_t *filesize);
|
||||
static off_t asciisetsize(int fd, off_t filesize);
|
||||
static int cloneit(char *file, int mode);
|
||||
|
||||
#if (__WORD_SIZE == 4)
|
||||
static char buffer[8192];
|
||||
#else
|
||||
static char buffer[2048];
|
||||
#endif
|
||||
static char line2[512];
|
||||
|
||||
static char *dir(path, full)
|
||||
char *path;
|
||||
int full;
|
||||
{
|
||||
char cmd[128];
|
||||
static char name[32];
|
||||
|
||||
tmpnam(name);
|
||||
|
||||
if(full)
|
||||
sprintf(cmd, "ls -l %s > %s", path, name);
|
||||
else
|
||||
sprintf(cmd, "ls -dA %s > %s", path, name);
|
||||
|
||||
system(cmd);
|
||||
|
||||
return(name);
|
||||
}
|
||||
|
||||
int DOascii()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
s = DOcommand("TYPE", "A");
|
||||
|
||||
type = TYPE_A;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DObinary()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
s = DOcommand("TYPE", "I");
|
||||
|
||||
type = TYPE_I;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOblock()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
s = DOcommand("MODE", "B");
|
||||
|
||||
mode = MODE_B;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOstream()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
s = DOcommand("MODE", "S");
|
||||
|
||||
mode = MODE_S;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOpwd()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
s = DOcommand("PWD", "");
|
||||
|
||||
if(s == 500 || s == 502)
|
||||
s = DOcommand("XPWD", "");
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOcd()
|
||||
{
|
||||
char *path;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Path: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
if(!strcmp(path, ".."))
|
||||
s = DOcommand("CDUP", "");
|
||||
else
|
||||
s = DOcommand("CWD", path);
|
||||
|
||||
if(s == 500 || s == 502) {
|
||||
if(!strcmp(path, ".."))
|
||||
s = DOcommand("XCUP", "");
|
||||
else
|
||||
s = DOcommand("XCWD", path);
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOmkdir()
|
||||
{
|
||||
char *path;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Directory: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
s = DOcommand("MKD", path);
|
||||
|
||||
if(s == 500 || s == 502)
|
||||
s = DOcommand("XMKD", path);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOrmdir()
|
||||
{
|
||||
char *path;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Directory: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
s = DOcommand("RMD", path);
|
||||
|
||||
if(s == 500 || s == 502)
|
||||
s = DOcommand("XRMD", path);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOdelete()
|
||||
{
|
||||
char *file;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
return(DOcommand("DELE", file));
|
||||
}
|
||||
|
||||
int DOmdtm()
|
||||
{
|
||||
char *file;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
return(DOcommand("MDTM", file));
|
||||
}
|
||||
|
||||
int DOsize()
|
||||
{
|
||||
char *file;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
return(DOcommand("SIZE", file));
|
||||
}
|
||||
|
||||
int DOstat()
|
||||
{
|
||||
char *file;
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(!linkopen) {
|
||||
printf("You must \"OPEN\" a connection first.\n");
|
||||
return(0);
|
||||
} else {
|
||||
return(DOcommand("STAT", ""));
|
||||
}
|
||||
}
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
return(DOcommand("STAT", file));
|
||||
}
|
||||
|
||||
int DOlist()
|
||||
{
|
||||
char *path;
|
||||
char *local;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2)
|
||||
path = "";
|
||||
|
||||
if(cmdargc < 3)
|
||||
local = "";
|
||||
else
|
||||
local = cmdargv[2];
|
||||
|
||||
if(*local == '\0')
|
||||
fd = 1;
|
||||
else
|
||||
fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", local, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("LIST", path, RETR, fd);
|
||||
|
||||
if(fd > 2)
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOnlst()
|
||||
{
|
||||
char *path;
|
||||
char *local;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2)
|
||||
path = "";
|
||||
|
||||
if(cmdargc < 3)
|
||||
local = "";
|
||||
else
|
||||
local = cmdargv[2];
|
||||
|
||||
if(*local == '\0')
|
||||
fd = 1;
|
||||
else
|
||||
fd = open(local, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", local, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("NLST", path, RETR, fd);
|
||||
|
||||
if(fd > 2)
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOretr()
|
||||
{
|
||||
char *file, *localfile;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Remote File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
localfile = file;
|
||||
else
|
||||
localfile = cmdargv[2];
|
||||
|
||||
fd = open(localfile, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("RETR", file, RETR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOrretr()
|
||||
{
|
||||
char *file, *localfile;
|
||||
int fd;
|
||||
int s;
|
||||
off_t filesize;
|
||||
char restart[16];
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Remote File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
localfile = file;
|
||||
else
|
||||
localfile = cmdargv[2];
|
||||
|
||||
fd = open(localfile, O_RDWR);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", localfile, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(type == TYPE_A) {
|
||||
if(asciisize(fd, &filesize)) {
|
||||
printf("Could not determine ascii file size of %s\n", localfile);
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
} else
|
||||
filesize = lseek(fd, 0, SEEK_END);
|
||||
|
||||
sprintf(restart, "%u", filesize);
|
||||
|
||||
s = DOcommand("REST", restart);
|
||||
|
||||
if(s != 350) {
|
||||
close(fd);
|
||||
return(s);
|
||||
}
|
||||
|
||||
s = DOdata("RETR", file, RETR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
char *ttime(time_t t)
|
||||
{
|
||||
struct tm *tm;
|
||||
static char tbuf[16];
|
||||
|
||||
tm = localtime(&t);
|
||||
|
||||
sprintf(tbuf, "%04d%02d%02d%02d%02d.%02d",
|
||||
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
|
||||
tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
return(tbuf);
|
||||
}
|
||||
|
||||
static int cloneit(file, mode)
|
||||
char *file;
|
||||
int mode;
|
||||
{
|
||||
int opr;
|
||||
int s;
|
||||
int ss;
|
||||
struct stat st;
|
||||
static unsigned short lcrc;
|
||||
static unsigned short ccrc;
|
||||
static unsigned long csize;
|
||||
static char ft;
|
||||
static unsigned long maj;
|
||||
static unsigned long min;
|
||||
static unsigned long uid;
|
||||
static unsigned long gid;
|
||||
static unsigned long fmode;
|
||||
static unsigned long size;
|
||||
static unsigned long mtime;
|
||||
struct utimbuf ut;
|
||||
unsigned short crc(char *fname);
|
||||
|
||||
if(mode == 1) {
|
||||
/* see if file exists locally */
|
||||
ss = stat(file, &st);
|
||||
|
||||
opr = printreply;
|
||||
printreply = 0;
|
||||
s = DOcommand("SITE FDET", file);
|
||||
printreply = opr;
|
||||
|
||||
if((s / 100) != 2)
|
||||
return(-1);
|
||||
|
||||
sscanf(reply, "%*d %c%lu%lu%lu%lu%lu%lu%lu",
|
||||
&ft, &maj, &min, &uid, &gid, &fmode, &size, &mtime);
|
||||
|
||||
if(ft == 'f') {
|
||||
opr = printreply;
|
||||
printreply = 0;
|
||||
s = DOcommand("SITE CCRC", file);
|
||||
printreply = opr;
|
||||
if((s / 100) != 2)
|
||||
return(-1);
|
||||
|
||||
sscanf(reply, "%*hu %*s%u%lu", &ccrc, &csize);
|
||||
if(ss < 0) return(-1);
|
||||
lcrc = crc(file);
|
||||
if(size != csize || size != st.st_size || ccrc != lcrc)
|
||||
return(-1);
|
||||
} else
|
||||
if(ss < 0 && ft == 'd') {
|
||||
s = mkdir(file, fmode);
|
||||
printf("mkdir %s\n", file);
|
||||
} else
|
||||
if((ss < 0) && (ft == 'b' || ft == 'c' || ft == 'p')) {
|
||||
s = mknod(file, fmode, maj << 8 | min);
|
||||
printf("mknod %s %lu %lu\n", file, maj, min);
|
||||
} else
|
||||
return(0);
|
||||
}
|
||||
ss = stat(file, &st);
|
||||
if(ss < 0)
|
||||
return(-1);
|
||||
if(st.st_uid != uid || st.st_gid != gid) {
|
||||
s = chown(file, uid, gid);
|
||||
printf("chown %lu:%lu %s\n", uid, gid, file);
|
||||
}
|
||||
if(st.st_mode != fmode) {
|
||||
s = chmod(file, fmode);
|
||||
printf("chmod %04lo %s\n", fmode, file);
|
||||
}
|
||||
if(st.st_mtime != mtime) {
|
||||
ut.actime = mtime;
|
||||
ut.modtime = mtime;
|
||||
s = utime(file, &ut);
|
||||
printf("touch -m -t %s %s\n", ttime(mtime), file);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOMretr()
|
||||
{
|
||||
char *files;
|
||||
int fd, s;
|
||||
char *p;
|
||||
FILE *fp;
|
||||
char name[32];
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
files = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Files: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
files = line2;
|
||||
}
|
||||
|
||||
tmpnam(name);
|
||||
|
||||
fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", name, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("NLST", files, RETR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
if(s == 226 || s == 250) {
|
||||
fp = fopen(name, "r");
|
||||
unlink(name);
|
||||
if(fp == (FILE *)NULL) {
|
||||
printf("Unable to open file listing.\n");
|
||||
return(0);
|
||||
}
|
||||
while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
|
||||
p = line2 + strlen(line2) - 1;
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
printf("Retrieving file: %s\n", line2); fflush(stdout);
|
||||
fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if(fd < 0)
|
||||
printf("Unable to open local file %s\n", line2);
|
||||
else {
|
||||
s = DOdata("RETR", line2, RETR, fd);
|
||||
close(fd);
|
||||
if(s < 0) break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
} else
|
||||
unlink(name);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOappe()
|
||||
{
|
||||
char *file, *remotefile;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Local File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
remotefile = file;
|
||||
else
|
||||
remotefile = cmdargv[2];
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", file, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("APPE", remotefile, STOR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOstor()
|
||||
{
|
||||
char *file, *remotefile;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Local File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
remotefile = file;
|
||||
else
|
||||
remotefile = cmdargv[2];
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", file, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("STOR", remotefile, STOR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOrstor()
|
||||
{
|
||||
char *file, *remotefile;
|
||||
int fd;
|
||||
int s;
|
||||
off_t filesize, rmtsize;
|
||||
char restart[16];
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Local File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
remotefile = file;
|
||||
else
|
||||
remotefile = cmdargv[2];
|
||||
|
||||
s = DOcommand("SIZE", remotefile);
|
||||
|
||||
if(s != 215)
|
||||
return(s);
|
||||
|
||||
rmtsize = atol(reply+4);
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", file, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(type == TYPE_A)
|
||||
filesize = asciisetsize(fd, rmtsize);
|
||||
else
|
||||
filesize = lseek(fd, rmtsize, SEEK_SET);
|
||||
|
||||
if(filesize != rmtsize) {
|
||||
printf("Could not set file start of %s\n", file);
|
||||
close(fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
sprintf(restart, "%u", rmtsize);
|
||||
|
||||
s = DOcommand("REST", restart);
|
||||
|
||||
if(s != 350) {
|
||||
close(fd);
|
||||
return(s);
|
||||
}
|
||||
|
||||
s = DOdata("STOR", remotefile, STOR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOstou()
|
||||
{
|
||||
char *file, *remotefile;
|
||||
int fd;
|
||||
int s;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
file = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Local File: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
file = line2;
|
||||
}
|
||||
|
||||
if(cmdargc < 3)
|
||||
remotefile = file;
|
||||
else
|
||||
remotefile = cmdargv[2];
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", file, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("STOU", remotefile, STOR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOMstor()
|
||||
{
|
||||
char *files;
|
||||
char *name;
|
||||
char *p;
|
||||
int fd, s;
|
||||
FILE *fp;
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
files = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Files: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
files = line2;
|
||||
}
|
||||
|
||||
name = dir(files, 0);
|
||||
|
||||
fp = fopen(name, "r");
|
||||
|
||||
if(fp == (FILE *)NULL) {
|
||||
printf("Unable to open listing file.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
|
||||
p = line2 + strlen(line2) - 1;
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
printf("Sending file: %s\n", line2); fflush(stdout);
|
||||
fd = open(line2, O_RDONLY);
|
||||
if(fd < 0)
|
||||
printf("Unable to open local file %s\n", line2);
|
||||
else {
|
||||
s = DOdata("STOR", line2, STOR, fd);
|
||||
close(fd);
|
||||
if(s < 0) break;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
unlink(name);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
static int asciisize(fd, filesize)
|
||||
int fd;
|
||||
off_t *filesize;
|
||||
{
|
||||
unsigned long count;
|
||||
char *p, *pp;
|
||||
int cnt;
|
||||
|
||||
count = 0;
|
||||
|
||||
while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
p = buffer; pp = buffer + cnt;
|
||||
count += cnt;
|
||||
while(p < pp)
|
||||
if(*p++ == '\n')
|
||||
count++;
|
||||
}
|
||||
|
||||
if(cnt == 0) {
|
||||
*filesize = count;
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static off_t asciisetsize(fd, filesize)
|
||||
int fd;
|
||||
off_t filesize;
|
||||
{
|
||||
off_t sp;
|
||||
int s;
|
||||
|
||||
sp = 0;
|
||||
|
||||
while(sp < filesize) {
|
||||
s = read(fd, buffer, 1);
|
||||
if(s < 0)
|
||||
return(-1);
|
||||
if(s == 0) break;
|
||||
sp++;
|
||||
if(*buffer == '\n')
|
||||
sp++;
|
||||
}
|
||||
|
||||
return(sp);
|
||||
}
|
||||
|
||||
int DOclone()
|
||||
{
|
||||
char *files;
|
||||
int fd, s;
|
||||
char *p;
|
||||
FILE *fp;
|
||||
char name[32];
|
||||
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
files = cmdargv[1];
|
||||
|
||||
tmpnam(name);
|
||||
|
||||
fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
|
||||
if(fd < 0) {
|
||||
printf("Could not open local file %s. Error %s\n", name, strerror(errno));
|
||||
return(0);
|
||||
}
|
||||
|
||||
s = DOdata("NLST", files, RETR, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
if(s == 226 || s == 250) {
|
||||
fp = fopen(name, "r");
|
||||
unlink(name);
|
||||
if(fp == (FILE *)NULL) {
|
||||
printf("Unable to open file listing.\n");
|
||||
return(0);
|
||||
}
|
||||
while(fgets(line2, sizeof(line2), fp) != (char *)NULL) {
|
||||
p = line2 + strlen(line2) - 1;
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
if(p >= line2 && (*p == '\r' || *p == '\n')) *p-- = '\0';
|
||||
cmdargv[1] = line2;
|
||||
if(cloneit(line2, 1)) {
|
||||
printf("Retrieving file: %s\n", line2); fflush(stdout);
|
||||
fd = open(line2, O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if(fd < 0)
|
||||
printf("Unable to open local file %s\n", line2);
|
||||
else {
|
||||
s = DOdata("RETR", line2, RETR, fd);
|
||||
close(fd);
|
||||
if(s < 0) break;
|
||||
}
|
||||
s = cloneit(line2, 2);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
} else
|
||||
unlink(name);
|
||||
|
||||
return(s);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/* file.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
int recvfile(int fd, int fdin);
|
||||
int sendfile(int fd, int fdout);
|
||||
int DOascii(void);
|
||||
int DObinary(void);
|
||||
int DOblock(void);
|
||||
int DOstream(void);
|
||||
int DOpwd(void);
|
||||
int DOcd(void);
|
||||
int DOmkdir(void);
|
||||
int DOrmdir(void);
|
||||
int DOdelete(void);
|
||||
int DOmdtm(void);
|
||||
int DOsize(void);
|
||||
int DOstat(void);
|
||||
int DOlist(void);
|
||||
int DOnlst(void);
|
||||
int DOretr(void);
|
||||
int DOrretr(void);
|
||||
int DOMretr(void);
|
||||
int DOappe(void);
|
||||
int DOstor(void);
|
||||
int DOrstor(void);
|
||||
int DOstou(void);
|
||||
int DOMstor(void);
|
||||
int DOclone(void);
|
|
@ -1,148 +0,0 @@
|
|||
.TH FTP 1
|
||||
.SH NAME
|
||||
ftp \- a File Transfer Protocol client for Minix
|
||||
.SH SYNOPSIS
|
||||
.B ftp
|
||||
.RI [ server_name ]
|
||||
.SH DESCRIPTION
|
||||
.B Ftp
|
||||
is a File Transfer Protocol client for Minix written by Michael Temari.
|
||||
.P
|
||||
There are no command line options for
|
||||
.B ftp
|
||||
except for the optional server name, which may be either a numeric IP address
|
||||
or a domain name resolvable by DNS.
|
||||
.P
|
||||
If a server name is specified a connection attempt will be made, and you
|
||||
will be prompted for a user name and password by the remote system.
|
||||
Following the login (or immediately, if no server name was specified), the
|
||||
.br
|
||||
.B ftp>
|
||||
.br
|
||||
prompt is displayed. The following commands are accepted at the prompt:
|
||||
.P
|
||||
Command: Description
|
||||
.br
|
||||
! Escape to a shell
|
||||
.br
|
||||
append Append a file to remote host
|
||||
.br
|
||||
ascii Set file transfer type to ascii
|
||||
.br
|
||||
binary Set file transfer type to binary
|
||||
.br
|
||||
block Set file transfer mode to block
|
||||
.br
|
||||
bye Close connection and exit
|
||||
.br
|
||||
cd Change directory on remote host
|
||||
.br
|
||||
close Close connection
|
||||
.br
|
||||
clone Clone a file
|
||||
.br
|
||||
del Remove file on remote host
|
||||
.br
|
||||
dir Display long form remote host directory listing
|
||||
.br
|
||||
exit Close connection and exit
|
||||
.br
|
||||
get Retrieve a file from remote host
|
||||
.br
|
||||
help Display this text
|
||||
.br
|
||||
lcd Change directory on local host
|
||||
.br
|
||||
ldir Display long form local host directory listing
|
||||
.br
|
||||
lls Display local host directory listing
|
||||
.br
|
||||
lmkdir Create directory on local host
|
||||
.br
|
||||
lpwd Display current directory on local host
|
||||
.br
|
||||
lrmdir Remove directory on local host
|
||||
.br
|
||||
ls Display remote host directory listing
|
||||
.br
|
||||
mget Retrieve multiple files from remote host
|
||||
.br
|
||||
mkdir Create directory on remote host
|
||||
.br
|
||||
mod Get file modification time
|
||||
.br
|
||||
mput Send multiple files to remote host
|
||||
.br
|
||||
noop Send the ftp NOOP command
|
||||
.br
|
||||
open Open connection to remote host
|
||||
.br
|
||||
pass Enter remote user password
|
||||
.br
|
||||
passive Toggle passive mode
|
||||
.br
|
||||
put Send a file to remote host
|
||||
.br
|
||||
putu Send a file to remote host(unique)
|
||||
.br
|
||||
pwd Display current directory on remote host
|
||||
.br
|
||||
quit Close connection and exit
|
||||
.br
|
||||
quote Send raw ftp command to remote host
|
||||
.br
|
||||
reget Restart a partial file retrieve from remote host
|
||||
.br
|
||||
remotehelp Display ftp commands implemented on remote host
|
||||
.br
|
||||
reput Restart a partial file send to remote host
|
||||
.br
|
||||
rm Remove file on remote host
|
||||
.br
|
||||
rmdir Remove directory on remote host
|
||||
.br
|
||||
site Send a site specific command
|
||||
.br
|
||||
size Get file size information
|
||||
.br
|
||||
status Get connection/file status information
|
||||
.br
|
||||
stream Set file transfer mode to stream
|
||||
.br
|
||||
system Get remote system type information
|
||||
.br
|
||||
user Enter remote user information
|
||||
.br
|
||||
ver Display client version information
|
||||
|
||||
.SH "SEE ALSO"
|
||||
.BR ftpd (8),
|
||||
.BR ftpget (1).
|
||||
.SH NOTES
|
||||
The FTP protocol passes unencrypted usernames and passwords to clients,
|
||||
so they are potentially exposed to evildoers with network sniffers. So be
|
||||
wary of using this to exchange files between your own accounts. Obviously
|
||||
if you have a root account on another system and the remote system will
|
||||
accept a login as root this is extremely dangerous. (Many ftp servers will
|
||||
not allow a connection by root).
|
||||
.P
|
||||
Text-mode (ASCII) transfers are the default mode, be sure to enter the
|
||||
"binary" command if you are downloading a program file or a compressed
|
||||
archive, in fact anything other than a text file from a machine with a
|
||||
different text-file format than Minix uses.
|
||||
.P
|
||||
If you are behind a firewall you probably need to use passive mode to
|
||||
successfully transfer files.
|
||||
|
||||
.SH BUGS
|
||||
None are known, but there may be some unknown ones. Version 1.00 corrects
|
||||
a bug in previous versions that would append a \\r (0xd) character to file
|
||||
names on the destination when an mget transfer was used in binary mode.
|
||||
|
||||
.SH AUTHOR
|
||||
The Minix httpd server was created by and is maintained by Michael Temari
|
||||
<Michael@TemWare.Com>. The earliest version was released in 1992, for use
|
||||
with Michael's TNet networking extensions for Minix 1.5.
|
||||
.P
|
||||
Man page compiled by Al Woodhull <asw@woodhull.com>
|
||||
.\" updated 2006-06-18
|
|
@ -1,407 +0,0 @@
|
|||
/* ftp.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* ftp An ftp client program for use with TNET.
|
||||
*
|
||||
* Usage: ftp [host]
|
||||
*
|
||||
* Version: 0.10 06/21/92 (pre-release not yet completed)
|
||||
* 0.20 07/01/92
|
||||
* 0.30 01/15/96 (Minix 1.7.1 initial release)
|
||||
* 0.40 08/27/96
|
||||
* 0.50 03/08/00
|
||||
* 1.00 12/12/03 (added ver command)
|
||||
* 1.01 02/07/05
|
||||
*
|
||||
* Author: Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "local.h"
|
||||
#include "file.h"
|
||||
#include "other.h"
|
||||
#include "net.h"
|
||||
|
||||
char *FtpVersion = "1.01 02/07/05";
|
||||
|
||||
int linkopen;
|
||||
int loggedin;
|
||||
int type;
|
||||
int format;
|
||||
int mode;
|
||||
int structure;
|
||||
int passive;
|
||||
int atty;
|
||||
|
||||
int cmdargc;
|
||||
char *cmdargv[NUMARGS];
|
||||
|
||||
int printreply = 1;
|
||||
char reply[1024];
|
||||
|
||||
/* Already declared in stdio.h */
|
||||
#define getline ftp_getline
|
||||
|
||||
static void makeargs(char *buff);
|
||||
int DOver(void);
|
||||
int DOhelp(void);
|
||||
static int getline(char *line, int len);
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
|
||||
static void makeargs(buff)
|
||||
char *buff;
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
for(i = 0; i < NUMARGS; i++)
|
||||
cmdargv[i] = (char *)0;
|
||||
|
||||
p = buff + strlen(buff) - 1;
|
||||
while(p >= buff)
|
||||
if(*p == '\r' || *p == '\n' || isspace(*p))
|
||||
*p-- = '\0';
|
||||
else
|
||||
break;
|
||||
|
||||
p = buff;
|
||||
cmdargc = 0;
|
||||
while(cmdargc < NUMARGS) {
|
||||
while(*p && isspace(*p))
|
||||
p++;
|
||||
if(*p == '\0')
|
||||
break;
|
||||
cmdargv[cmdargc++] = p;
|
||||
while(*p && !isspace(*p)) {
|
||||
if(cmdargc == 1)
|
||||
*p = tolower(*p);
|
||||
p++;
|
||||
}
|
||||
if(*p == '\0')
|
||||
break;
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
int readline(prompt, buff, len)
|
||||
char *prompt;
|
||||
char *buff;
|
||||
int len;
|
||||
{
|
||||
char *p;
|
||||
|
||||
printf(prompt); fflush(stdout);
|
||||
|
||||
if(fgets(buff, len, stdin) == (char *)NULL) {
|
||||
printf("\nEnd of file on input!\n");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
p = buff + strlen(buff) - 1;
|
||||
while(p >= buff)
|
||||
if(*p == '\r' || *p == '\n' || isspace(*p))
|
||||
*p-- = '\0';
|
||||
else
|
||||
break;
|
||||
|
||||
if(!atty) {
|
||||
printf("%s\n", buff);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int getline(line, len)
|
||||
char *line;
|
||||
int len;
|
||||
{
|
||||
int s;
|
||||
int gotcr;
|
||||
|
||||
/* leave room for at end for null */
|
||||
len--;
|
||||
|
||||
/* got to be able to put in at least 1 character */
|
||||
if(len < 1)
|
||||
return(-1);
|
||||
|
||||
gotcr = 0;
|
||||
while(len-- > 0) {
|
||||
s = read(ftpcomm_fd, line, 1);
|
||||
if(s != 1)
|
||||
return(-1);
|
||||
if(*line == '\n')
|
||||
break;
|
||||
gotcr = (*line == '\r');
|
||||
line++;
|
||||
}
|
||||
if(gotcr)
|
||||
--line;
|
||||
|
||||
*line = '\0';
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOgetreply()
|
||||
{
|
||||
int firsttime;
|
||||
int s;
|
||||
char code[4];
|
||||
|
||||
do {
|
||||
firsttime = 1;
|
||||
do {
|
||||
if((s = getline(reply, sizeof(reply))) < 0)
|
||||
return(s);
|
||||
if(printreply) {
|
||||
printf("%s\n", reply);
|
||||
fflush(stdout);
|
||||
}
|
||||
if(firsttime) {
|
||||
firsttime = 0;
|
||||
strncpy(code, reply, 3);
|
||||
code[3] = '\0';
|
||||
}
|
||||
} while(strncmp(reply, code, 3) || reply[3] == '-');
|
||||
s = atoi(code);
|
||||
} while(s < 200 && s != 125 && s != 150);
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOcmdcheck()
|
||||
{
|
||||
if(!linkopen) {
|
||||
printf("You must \"OPEN\" a connection first.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
if(!loggedin) {
|
||||
printf("You must login first.\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOcommand(ftpcommand, ftparg)
|
||||
char *ftpcommand;
|
||||
char *ftparg;
|
||||
{
|
||||
int s;
|
||||
#if 1
|
||||
static char ss[64];
|
||||
if(*ftparg)
|
||||
sprintf(ss, "%s %s\r\n", ftpcommand, ftparg);
|
||||
else
|
||||
sprintf(ss, "%s\r\n", ftpcommand);
|
||||
|
||||
s = write(ftpcomm_fd, ss, strlen(ss));
|
||||
if(s != strlen(ss))
|
||||
return(-1);
|
||||
|
||||
#else
|
||||
s = write(ftpcomm_fd, ftpcommand, strlen(ftpcommand));
|
||||
if(s != strlen(ftpcommand))
|
||||
return(-1);
|
||||
|
||||
if(*ftparg) {
|
||||
s = write(ftpcomm_fd, " ", 1);
|
||||
if(s != 1)
|
||||
return(-1);
|
||||
|
||||
s = write(ftpcomm_fd, ftparg, strlen(ftparg));
|
||||
if(s != strlen(ftparg))
|
||||
return(-1);
|
||||
}
|
||||
|
||||
s = write(ftpcomm_fd, "\r\n", 2);
|
||||
if(s != 2)
|
||||
return(-1);
|
||||
#endif
|
||||
|
||||
return(DOgetreply());
|
||||
}
|
||||
|
||||
int DOver()
|
||||
{
|
||||
printf("FTP Version %s\n", FtpVersion);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOhelp()
|
||||
{
|
||||
char junk[10];
|
||||
|
||||
printf("Command: Description\n");
|
||||
printf("! Escape to a shell\n");
|
||||
printf("append Append a file to remote host\n");
|
||||
printf("ascii Set file transfer type to ascii\n");
|
||||
printf("binary Set file transfer type to binary\n");
|
||||
printf("block Set file transfer mode to block\n");
|
||||
printf("bye Close connection and exit\n");
|
||||
printf("cd Change directory on remote host\n");
|
||||
printf("close Close connection\n");
|
||||
printf("clone Clone a file\n");
|
||||
printf("del Remove file on remote host\n");
|
||||
printf("dir Display long form remote host directory listing\n");
|
||||
printf("exit Close connection and exit\n");
|
||||
printf("get Retrieve a file from remote host\n");
|
||||
printf("help Display this text\n");
|
||||
|
||||
if(readline("Press ENTER to continue... ", junk, sizeof(junk)))
|
||||
return(-1);
|
||||
|
||||
printf("lcd Change directory on local host\n");
|
||||
printf("ldir Display long form local host directory listing\n");
|
||||
printf("lls Display local host directory listing\n");
|
||||
printf("lmkdir Create directory on local host\n");
|
||||
printf("lpwd Display current directory on local host\n");
|
||||
printf("lrmdir Remove directory on local host\n");
|
||||
printf("ls Display remote host directory listing\n");
|
||||
printf("mget Retrieve multiple files from remote host\n");
|
||||
printf("mkdir Create directory on remote host\n");
|
||||
printf("mod Get file modification time\n");
|
||||
printf("mput Send multiple files to remote host\n");
|
||||
printf("noop Send the ftp NOOP command\n");
|
||||
|
||||
if(readline("Press ENTER to continue... ", junk, sizeof(junk)))
|
||||
return(-1);
|
||||
|
||||
printf("open Open connection to remote host\n");
|
||||
printf("pass Enter remote user password\n");
|
||||
printf("passive Toggle passive mode\n");
|
||||
printf("put Send a file to remote host\n");
|
||||
printf("putu Send a file to remote host(unique)\n");
|
||||
printf("pwd Display current directory on remote host\n");
|
||||
printf("quit Close connection and exit\n");
|
||||
printf("quote Send raw ftp command to remote host\n");
|
||||
printf("reget Restart a partial file retrieve from remote host\n");
|
||||
printf("remotehelp Display ftp commands implemented on remote host\n");
|
||||
printf("reput Restart a partial file send to remote host\n");
|
||||
printf("rm Remove file on remote host\n");
|
||||
printf("rmdir Remove directory on remote host\n");
|
||||
|
||||
if(readline("Press ENTER to continue... ", junk, sizeof(junk)))
|
||||
return(-1);
|
||||
|
||||
printf("site Send a site specific command\n");
|
||||
printf("size Get file size information\n");
|
||||
printf("status Get connection/file status information\n");
|
||||
printf("stream Set file transfer mode to stream\n");
|
||||
printf("system Get remote system type information\n");
|
||||
printf("user Enter remote user information\n");
|
||||
printf("ver Display client version information\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
struct commands {
|
||||
char *name;
|
||||
int(*func) (void);
|
||||
};
|
||||
|
||||
static struct commands commands[] = {
|
||||
"!", DOlshell,
|
||||
"append", DOappe,
|
||||
"ascii", DOascii,
|
||||
"binary", DObinary,
|
||||
"block", DOblock,
|
||||
"bye", DOquit,
|
||||
"cd", DOcd,
|
||||
"close", DOclose,
|
||||
"clone", DOclone,
|
||||
"del", DOdelete,
|
||||
"dir", DOlist,
|
||||
"exit", DOquit,
|
||||
"get", DOretr,
|
||||
"help", DOhelp,
|
||||
"lcd", DOlcd,
|
||||
"ldir", DOllist,
|
||||
"lls", DOlnlst,
|
||||
"lmkdir", DOlmkdir,
|
||||
"lpwd", DOlpwd,
|
||||
"lrmdir", DOlrmdir,
|
||||
"ls", DOnlst,
|
||||
"mget", DOMretr,
|
||||
"mkdir", DOmkdir,
|
||||
"mod", DOmdtm,
|
||||
"mput", DOMstor,
|
||||
"noop", DOnoop,
|
||||
"open", DOopen,
|
||||
"pass", DOpass,
|
||||
"passive", DOpassive,
|
||||
"put", DOstor,
|
||||
"putu", DOstou,
|
||||
"pwd", DOpwd,
|
||||
"quit", DOquit,
|
||||
"quote", DOquote,
|
||||
"reget", DOrretr,
|
||||
"remotehelp", DOremotehelp,
|
||||
"reput", DOrstor,
|
||||
"rm", DOdelete,
|
||||
"rmdir", DOrmdir,
|
||||
"site", DOsite,
|
||||
"size", DOsize,
|
||||
"status", DOstat,
|
||||
"stream", DOstream,
|
||||
"system", DOsyst,
|
||||
"user", DOuser,
|
||||
"ver", DOver,
|
||||
"", (int (*)())0
|
||||
};
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int s;
|
||||
struct commands *cmd;
|
||||
static char buffer[128];
|
||||
|
||||
if(NETinit())
|
||||
return(-1);
|
||||
|
||||
FTPinit();
|
||||
|
||||
s = 0;
|
||||
|
||||
if(argc > 1) {
|
||||
sprintf(buffer, "open %s ", argv[1]);
|
||||
makeargs(buffer);
|
||||
s = DOopen();
|
||||
if(atty && s > 0) {
|
||||
sprintf(buffer, "user");
|
||||
makeargs(buffer);
|
||||
s = DOuser();
|
||||
}
|
||||
}
|
||||
|
||||
while(s >= 0) {
|
||||
s = readline("ftp>", buffer, sizeof(buffer));
|
||||
if(s < 0) break;
|
||||
makeargs(buffer);
|
||||
if(cmdargc == 0) continue;
|
||||
for(cmd = commands; *cmd->name != '\0'; cmd++)
|
||||
if(!strcmp(cmdargv[0], cmd->name))
|
||||
break;
|
||||
if(*cmd->name != '\0')
|
||||
s = (*cmd->func)();
|
||||
else {
|
||||
s = 0;
|
||||
printf("Command \"%s\" not recognized.\n", cmdargv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/* ftp.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
extern int linkopen;
|
||||
extern int loggedin;
|
||||
extern int type;
|
||||
extern int format;
|
||||
extern int mode;
|
||||
extern int structure;
|
||||
extern int passive;
|
||||
extern int atty;
|
||||
|
||||
#define NUMARGS 10
|
||||
extern int cmdargc;
|
||||
extern char *cmdargv[NUMARGS];
|
||||
|
||||
extern int printreply;
|
||||
extern char reply[1024];
|
||||
|
||||
#define RETR 0
|
||||
#define STOR 1
|
||||
|
||||
#define TYPE_A 0
|
||||
#define TYPE_I 1
|
||||
|
||||
#define MODE_S 0
|
||||
#define MODE_B 1
|
||||
|
||||
#define MODE_B_EOF 64
|
||||
|
||||
int readline(char *prompt, char *buff, int len);
|
||||
int DOgetreply(void);
|
||||
int DOcmdcheck(void);
|
||||
int DOcommand(char *ftpcommand, char *ftparg);
|
|
@ -1,134 +0,0 @@
|
|||
/* local.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "local.h"
|
||||
|
||||
static char line2[512];
|
||||
|
||||
static void dodir(char *path, int full);
|
||||
|
||||
int DOlpwd()
|
||||
{
|
||||
if(getcwd(line2, sizeof(line2)) == (char *)NULL)
|
||||
printf("Could not determine local directory. %s\n", strerror(errno));
|
||||
else
|
||||
printf("Current local directory: %s\n", line2);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOlcd()
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Path: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
if(chdir(path))
|
||||
printf("Could not change local directory. %s\n", strerror(errno));
|
||||
else
|
||||
return(DOlpwd());
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOlmkdir()
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Path: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
if(mkdir(path, 0777))
|
||||
printf("Could not make directory %s. %s\n", path, strerror(errno));
|
||||
else
|
||||
printf("Directory created.\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOlrmdir()
|
||||
{
|
||||
char *path;
|
||||
|
||||
path = cmdargv[1];
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Path: ", line2, sizeof(line2)) < 0)
|
||||
return(-1);
|
||||
path = line2;
|
||||
}
|
||||
|
||||
if(rmdir(path))
|
||||
printf("Could not remove directory %s. %s\n", path, strerror(errno));
|
||||
else
|
||||
printf("Directory removed.\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOllist(void)
|
||||
{
|
||||
dodir(".", 1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOlnlst(void)
|
||||
{
|
||||
dodir(".", 0);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOlshell(void)
|
||||
{
|
||||
(void) system("$SHELL");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void dodir(path, full)
|
||||
char *path;
|
||||
int full;
|
||||
{
|
||||
static char cmd[128];
|
||||
static char name[32];
|
||||
|
||||
(void) tmpnam(name);
|
||||
|
||||
if(full)
|
||||
sprintf(cmd, "ls -l %s > %s", path, name);
|
||||
else
|
||||
sprintf(cmd, "ls %s > %s", path, name);
|
||||
|
||||
(void) system(cmd);
|
||||
sprintf(cmd, "more %s", name);
|
||||
(void) system(cmd);
|
||||
sprintf(cmd, "rm %s", name);
|
||||
(void) system(cmd);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/* local.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
int DOlpwd(void);
|
||||
int DOlcd(void);
|
||||
int DOlmkdir(void);
|
||||
int DOlrmdir(void);
|
||||
int DOllist(void);
|
||||
int DOlnlst(void);
|
||||
int DOlshell(void);
|
|
@ -1,569 +0,0 @@
|
|||
/* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <net/netlib.h>
|
||||
#include <net/hton.h>
|
||||
#include <net/gen/netdb.h>
|
||||
#include <net/gen/in.h>
|
||||
#include <net/gen/inet.h>
|
||||
#include <net/gen/tcp.h>
|
||||
#include <net/gen/tcp_io.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "xfer.h"
|
||||
#include "net.h"
|
||||
|
||||
void donothing(int sig);
|
||||
|
||||
int ftpcomm_fd;
|
||||
static ipaddr_t myip;
|
||||
static ipaddr_t hostip;
|
||||
static char host[256];
|
||||
static int lpid;
|
||||
|
||||
int NETinit()
|
||||
{
|
||||
int s;
|
||||
char *tcp_device;
|
||||
int tcp_fd;
|
||||
nwio_tcpconf_t nwio_tcpconf;
|
||||
|
||||
/* All this just to get our ip address */
|
||||
|
||||
if((tcp_device = getenv("TCP_DEVICE")) == (char *)NULL)
|
||||
tcp_device = TCP_DEVICE;
|
||||
|
||||
tcp_fd = open(tcp_device, O_RDWR);
|
||||
if(tcp_fd < 0) {
|
||||
perror("ftp: Could not open tcp_device");
|
||||
return(-1);
|
||||
}
|
||||
s = ioctl(tcp_fd, NWIOGTCPCONF, &nwio_tcpconf);
|
||||
if(s < 0) {
|
||||
perror("ftp: Could not get tcp configuration");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
myip = nwio_tcpconf.nwtc_locaddr;
|
||||
|
||||
close(tcp_fd);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOopen()
|
||||
{
|
||||
nwio_tcpconf_t tcpconf;
|
||||
nwio_tcpcl_t tcpcopt;
|
||||
char *tcp_device;
|
||||
tcpport_t port;
|
||||
int s;
|
||||
struct hostent *hp;
|
||||
struct servent *servent;
|
||||
|
||||
if(linkopen) {
|
||||
printf("Use \"CLOSE\" to close the connection first.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Host: ", host, sizeof(host)) < 0)
|
||||
return(-1);
|
||||
} else
|
||||
strncpy(host, cmdargv[1], sizeof(host));
|
||||
|
||||
if((servent = getservbyname("ftp", "tcp")) == (struct servent *)NULL) {
|
||||
fprintf(stderr, "ftp: Could not find ftp tcp service\n");
|
||||
port = htons(21);
|
||||
} else
|
||||
port = (tcpport_t)servent->s_port;
|
||||
|
||||
hp = gethostbyname(host);
|
||||
if(hp == (struct hostent *)NULL) {
|
||||
hostip = (ipaddr_t)0;
|
||||
printf("Unresolved host %s\n", host);
|
||||
return(0);
|
||||
} else
|
||||
memcpy((char *) &hostip, (char *) hp->h_addr, hp->h_length);
|
||||
|
||||
/* This HACK allows the server to establish data connections correctly */
|
||||
/* when using the loopback device to talk to ourselves */
|
||||
if((hostip & ntohl(0xFF000000)) == inet_addr("127.0.0.0"))
|
||||
hostip = myip;
|
||||
|
||||
if((tcp_device = getenv("TCP_DEVICE")) == NULL)
|
||||
tcp_device = "/dev/tcp";
|
||||
|
||||
if((ftpcomm_fd = open(tcp_device, O_RDWR)) < 0) {
|
||||
perror("ftp: open error on tcp device");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
|
||||
tcpconf.nwtc_remaddr = hostip;
|
||||
tcpconf.nwtc_remport = port;
|
||||
|
||||
s = ioctl(ftpcomm_fd, NWIOSTCPCONF, &tcpconf);
|
||||
if(s < 0) {
|
||||
perror("ftp: ioctl error on NWIOSTCPCONF");
|
||||
close(ftpcomm_fd);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
tcpcopt.nwtcl_flags = 0;
|
||||
|
||||
s = ioctl(ftpcomm_fd, NWIOTCPCONN, &tcpcopt);
|
||||
if(s < 0) {
|
||||
perror("ftp: ioctl error on NWIOTCPCONN");
|
||||
close(ftpcomm_fd);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
s = ioctl(ftpcomm_fd, NWIOGTCPCONF, &tcpconf);
|
||||
if(s < 0) {
|
||||
perror("ftp: ioctl error on NWIOGTCPCONF");
|
||||
close(ftpcomm_fd);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
s = DOgetreply();
|
||||
|
||||
if(s < 0) {
|
||||
close(ftpcomm_fd);
|
||||
return(s);
|
||||
}
|
||||
|
||||
if(s != 220) {
|
||||
close(ftpcomm_fd);
|
||||
return(0);
|
||||
}
|
||||
|
||||
linkopen = 1;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOclose()
|
||||
{
|
||||
if(!linkopen) {
|
||||
printf("You can't close a connection that isn't open.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
close(ftpcomm_fd);
|
||||
|
||||
linkopen = 0;
|
||||
loggedin = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOquit()
|
||||
{
|
||||
int s;
|
||||
|
||||
if(linkopen) {
|
||||
s = DOcommand("QUIT", "");
|
||||
s = DOclose();
|
||||
}
|
||||
|
||||
printf("FTP done.\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void donothing(sig)
|
||||
int sig;
|
||||
{
|
||||
}
|
||||
|
||||
int DOdata(datacom, file, direction, fd)
|
||||
char *datacom;
|
||||
char *file;
|
||||
int direction; /* RETR or STOR */
|
||||
int fd;
|
||||
{
|
||||
nwio_tcpconf_t tcpconf;
|
||||
nwio_tcpcl_t tcplopt, tcpcopt;
|
||||
char *tcp_device;
|
||||
static int ftpdata_fd = -1;
|
||||
char *buff;
|
||||
ipaddr_t ripaddr;
|
||||
tcpport_t rport;
|
||||
static tcpport_t lport;
|
||||
int s;
|
||||
int i;
|
||||
int wpid;
|
||||
int cs;
|
||||
int pfd[2];
|
||||
char dummy;
|
||||
char port[32];
|
||||
int wasopen;
|
||||
|
||||
lport = htons(0xF000);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("DOdata %s %s %d %d\n", datacom, file, direction, fd);
|
||||
#endif
|
||||
|
||||
ripaddr = hostip;
|
||||
rport = htons(2);
|
||||
|
||||
/* here we set up a connection to listen on if not passive mode */
|
||||
/* otherwise we use this to connect for passive mode */
|
||||
|
||||
if((tcp_device = getenv("TCP_DEVICE")) == NULL)
|
||||
tcp_device = "/dev/tcp";
|
||||
|
||||
if(ftpdata_fd >= 0 && mode != MODE_B) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
}
|
||||
|
||||
wasopen = (ftpdata_fd >= 0);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("wasopen = %d\n", wasopen);
|
||||
#endif
|
||||
|
||||
if(wasopen)
|
||||
goto WASOPEN;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("b4 open = %d\n", ftpdata_fd);
|
||||
#endif
|
||||
|
||||
if(ftpdata_fd == -1)
|
||||
if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
|
||||
perror("ftp: open error on tcp device");
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("at open = %d\n", ftpdata_fd);
|
||||
#endif
|
||||
|
||||
if(passive) {
|
||||
#ifdef DEBUG
|
||||
printf("b4 PASV command\n");
|
||||
#endif
|
||||
s = DOcommand("PASV", "");
|
||||
#ifdef DEBUG
|
||||
printf("PASV command returned %d\n", s);
|
||||
#endif
|
||||
if(s != 227) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(s);
|
||||
}
|
||||
/* decode host and port */
|
||||
buff = reply;
|
||||
while(*buff && (*buff != '(')) buff++;
|
||||
buff++;
|
||||
ripaddr = (ipaddr_t)0;
|
||||
for(i = 0; i < 4; i++) {
|
||||
ripaddr = (ripaddr << 8) + (ipaddr_t)atoi(buff);
|
||||
if((buff = strchr(buff, ',')) == (char *)0) {
|
||||
printf("Could not parse PASV reply\n");
|
||||
return(0);
|
||||
}
|
||||
buff++;
|
||||
}
|
||||
rport = (tcpport_t)atoi(buff);
|
||||
if((buff = strchr(buff, ',')) == (char *)0) {
|
||||
printf("Could not parse PASV reply\n");
|
||||
return(0);
|
||||
}
|
||||
buff++;
|
||||
rport = (rport << 8) + (tcpport_t)atoi(buff);
|
||||
ripaddr = ntohl(ripaddr);
|
||||
rport = ntohs(rport);
|
||||
#ifdef DEBUG
|
||||
printf("PASV %08x %04x\n", ripaddr, rport);
|
||||
#endif
|
||||
}
|
||||
|
||||
while(1) {
|
||||
tcpconf.nwtc_flags = NWTC_SET_RA | NWTC_SET_RP;
|
||||
if(passive || ntohs(lport) >= 0xF000) {
|
||||
tcpconf.nwtc_flags |= NWTC_LP_SEL;
|
||||
} else {
|
||||
/* For no good reason Sun hosts don't like it if they have to
|
||||
* connect to the same port twice in a short time...
|
||||
*/
|
||||
lport = htons(ntohs(lport) + 1);
|
||||
tcpconf.nwtc_flags |= NWTC_LP_SET;
|
||||
tcpconf.nwtc_locport = lport;
|
||||
}
|
||||
|
||||
tcpconf.nwtc_remaddr = ripaddr;
|
||||
tcpconf.nwtc_remport = rport;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("b4 STCPCONF locport = %d\n", lport);
|
||||
#endif
|
||||
|
||||
s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
|
||||
#ifdef DEBUG
|
||||
printf("at STCPCONF %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s < 0) {
|
||||
if(errno == EADDRINUSE) continue;
|
||||
perror("ftp: ioctl error on NWIOSTCPCONF");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("b4 GTCPCONF\n");
|
||||
#endif
|
||||
s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
|
||||
#ifdef DEBUG
|
||||
printf("at GTCPCONF %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s < 0) {
|
||||
perror("ftp: ioctl error on NWIOGTCPCONF");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(0);
|
||||
}
|
||||
lport = tcpconf.nwtc_locport;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("lport = %04x\n", lport);
|
||||
#endif
|
||||
|
||||
if(passive) {
|
||||
/* passive mode we connect to them */
|
||||
tcpcopt.nwtcl_flags = 0;
|
||||
#ifdef DEBUG
|
||||
printf("Doing TCPCONN\n");
|
||||
#endif
|
||||
s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
|
||||
#ifdef DEBUG
|
||||
printf("TCPCONN %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s < 0) {
|
||||
perror("ftp: error on ioctl NWIOTCPCONN");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(0);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("GTCPCONF\n");
|
||||
#endif
|
||||
s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
|
||||
#ifdef DEBUG
|
||||
printf("GTCPCONF %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s < 0) {
|
||||
perror("ftp: error on ioctl NWIOGTCPCONF");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(0);
|
||||
}
|
||||
} else {
|
||||
/* we listen for them */
|
||||
tcplopt.nwtcl_flags = 0;
|
||||
#ifdef DEBUG
|
||||
printf("Listen\n");
|
||||
#endif
|
||||
|
||||
if (pipe(pfd) < 0) {
|
||||
perror("ftp: could not create a pipe");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(0);
|
||||
}
|
||||
lpid = fork();
|
||||
if(lpid < 0) {
|
||||
perror("ftp: could not fork listener");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
close(pfd[0]);
|
||||
close(pfd[1]);
|
||||
return(0);
|
||||
} else if(lpid == 0) {
|
||||
#ifdef DEBUG
|
||||
printf("Child here\n");
|
||||
#endif
|
||||
close(pfd[0]);
|
||||
signal(SIGALRM, donothing);
|
||||
alarm(15);
|
||||
close(pfd[1]);
|
||||
#ifdef DEBUG
|
||||
printf("child TCPLISTEN\n");
|
||||
#endif
|
||||
s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
|
||||
alarm(0);
|
||||
#ifdef DEBUG
|
||||
printf("listen %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s < 0)
|
||||
exit(errno); /* error */
|
||||
else
|
||||
exit(0); /* connection made */
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Fork = %d\n", lpid);
|
||||
#endif
|
||||
/* Wait for the pipe to close, then the listener is ready (almost). */
|
||||
close(pfd[1]);
|
||||
(void) read(pfd[0], &dummy, 1);
|
||||
close(pfd[0]);
|
||||
while(1) {
|
||||
wpid = waitpid(lpid, &cs, WNOHANG);
|
||||
#ifdef DEBUG
|
||||
printf("waitpid %d %d\n", wpid, cs);
|
||||
printf("GTCPCONF loop\n");
|
||||
#endif
|
||||
if(wpid != 0) break;
|
||||
signal(SIGALRM, donothing);
|
||||
alarm(1);
|
||||
s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
|
||||
alarm(0);
|
||||
#ifdef DEBUG
|
||||
printf("GTCPCONF loop %d %d\n", s, errno);
|
||||
#endif
|
||||
if(s == -1) break;
|
||||
sleep(1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("GTCPCONF = %d\n", s);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define hiword(x) ((u16_t)((x) >> 16))
|
||||
#define loword(x) ((u16_t)(x & 0xffff))
|
||||
#define hibyte(x) (((x) >> 8) & 0xff)
|
||||
#define lobyte(x) ((x) & 0xff)
|
||||
|
||||
if(!passive) {
|
||||
if(wpid != 0) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
cs = (cs >> 8) & 0x00ff;
|
||||
printf("Child listener error %s\n", strerror(cs));
|
||||
return(0);
|
||||
}
|
||||
sprintf(port, "%u,%u,%u,%u,%u,%u",
|
||||
hibyte(hiword(ntohl(myip))), lobyte(hiword(ntohl(myip))),
|
||||
hibyte(loword(ntohl(myip))), lobyte(loword(ntohl(myip))),
|
||||
hibyte(ntohs(lport)), lobyte(ntohs(lport)));
|
||||
#ifdef DEBUG
|
||||
printf("sending port command %s\n", port);
|
||||
#endif
|
||||
s = DOcommand("PORT", port);
|
||||
#ifdef DEBUG
|
||||
printf("port command = %d\n", s);
|
||||
#endif
|
||||
if(s != 200) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
kill(lpid, SIGKILL);
|
||||
(void) wait(&cs);
|
||||
return(s);
|
||||
}
|
||||
}
|
||||
|
||||
WASOPEN:
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("doing data command %s %s\n", datacom, file);
|
||||
#endif
|
||||
s = DOcommand(datacom, file);
|
||||
#ifdef DEBUG
|
||||
printf("do command reply %d\n", s);
|
||||
#endif
|
||||
if(s == 125 || s == 150) {
|
||||
if(!passive && !wasopen) {
|
||||
while(1) {
|
||||
#ifdef DEBUG
|
||||
printf("Waiting for child %d\n", lpid);
|
||||
#endif
|
||||
s = wait(&cs);
|
||||
#ifdef DEBUG
|
||||
printf("Wait returned %d cs=%d errno=%d\n", s, cs, errno);
|
||||
#endif
|
||||
if(s < 0 || s == lpid)
|
||||
break;
|
||||
}
|
||||
if(s < 0) {
|
||||
perror("wait error:");
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
kill(lpid, SIGKILL);
|
||||
(void) wait(&cs);
|
||||
return(s);
|
||||
}
|
||||
if((cs & 0x00ff)) {
|
||||
printf("Child listener failed %04x\n", cs);
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(-1);
|
||||
}
|
||||
cs = (cs >> 8) & 0x00ff;
|
||||
if(cs) {
|
||||
printf("Child listener error %s\n", strerror(cs));
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
return(DOgetreply());
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Before recvfile/sendfile call\n");
|
||||
#endif
|
||||
switch(direction) {
|
||||
case RETR:
|
||||
s = recvfile(fd, ftpdata_fd);
|
||||
break;
|
||||
case STOR:
|
||||
s = sendfile(fd, ftpdata_fd);
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("send/recieve %d\n", s);
|
||||
#endif
|
||||
if(mode != MODE_B) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
}
|
||||
|
||||
s = DOgetreply();
|
||||
#ifdef DEBUG
|
||||
printf("send/recieve reply %d\n", s);
|
||||
#endif
|
||||
if(mode == MODE_B && s == 226) {
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
}
|
||||
} else {
|
||||
if(!passive) {
|
||||
kill(lpid, SIGKILL);
|
||||
(void) wait(&cs);
|
||||
}
|
||||
close(ftpdata_fd);
|
||||
ftpdata_fd = -1;
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/* net.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
int NETinit(void);
|
||||
int DOopen(void);
|
||||
int DOclose(void);
|
||||
int DOquit(void);
|
||||
int DOdata(char *datacom, char *file, int direction, int fd);
|
||||
|
||||
extern int ftpcomm_fd;
|
|
@ -1,173 +0,0 @@
|
|||
/* other.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* ftp An ftp client program for use with TNET.
|
||||
*
|
||||
* Author: Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "other.h"
|
||||
|
||||
static int docmdargs(char *cmd, int fa);
|
||||
|
||||
void FTPinit()
|
||||
{
|
||||
linkopen = 0;
|
||||
loggedin = 0;
|
||||
type = TYPE_A;
|
||||
format = 0;
|
||||
mode = MODE_S;
|
||||
structure = 0;
|
||||
passive = 0;
|
||||
atty = isatty(0);
|
||||
}
|
||||
|
||||
int DOpass()
|
||||
{
|
||||
int s;
|
||||
struct termios oldtty, newtty;
|
||||
char *pass;
|
||||
char password[64];
|
||||
|
||||
if(!linkopen) {
|
||||
printf("You must \"OPEN\" a connection first.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
pass = cmdargv[1];
|
||||
|
||||
s = 0;
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(atty) {
|
||||
tcgetattr(fileno(stdout), &oldtty);
|
||||
newtty = oldtty;
|
||||
newtty.c_lflag &= ~ECHO;
|
||||
tcsetattr(fileno(stdout), TCSANOW, &newtty);
|
||||
}
|
||||
s = readline("Password: ", password, sizeof(password));
|
||||
if(atty) {
|
||||
tcsetattr(fileno(stdout), TCSANOW, &oldtty);
|
||||
printf("\n");
|
||||
}
|
||||
pass = password;
|
||||
}
|
||||
|
||||
if(s < 0)
|
||||
return(-1);
|
||||
|
||||
s = DOcommand("PASS", pass);
|
||||
|
||||
if(s == 230)
|
||||
loggedin = 1;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOuser()
|
||||
{
|
||||
char *user;
|
||||
int s;
|
||||
char username[32];
|
||||
|
||||
if(!linkopen) {
|
||||
printf("You must \"OPEN\" a connection first.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
loggedin = 0;
|
||||
|
||||
user = cmdargv[1];
|
||||
|
||||
s = 0;
|
||||
|
||||
if(cmdargc < 2) {
|
||||
if(readline("Username: ", username, sizeof(username)) < 0)
|
||||
return(-1);
|
||||
user = username;
|
||||
}
|
||||
|
||||
s = DOcommand("USER", user);
|
||||
|
||||
if(atty && s == 331) {
|
||||
cmdargv[0] = "password";
|
||||
cmdargc = 1;
|
||||
return(DOpass());
|
||||
}
|
||||
|
||||
if(s == 230)
|
||||
loggedin = 1;
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int DOnoop()
|
||||
{
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
return(DOcommand("NOOP", ""));
|
||||
}
|
||||
|
||||
int DOpassive()
|
||||
{
|
||||
passive = 1 - passive;
|
||||
|
||||
printf("Passive mode is now %s\n", (passive ? "ON" : "OFF"));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int DOsyst()
|
||||
{
|
||||
if(DOcmdcheck())
|
||||
return(0);
|
||||
|
||||
return(DOcommand("SYST", ""));
|
||||
}
|
||||
|
||||
int DOremotehelp()
|
||||
{
|
||||
if(!linkopen) {
|
||||
printf("You must \"OPEN\" a connection first.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(DOcommand("HELP", ""));
|
||||
}
|
||||
|
||||
static int docmdargs(cmd, fa)
|
||||
char *cmd;
|
||||
int fa;
|
||||
{
|
||||
int i;
|
||||
static char args[512];
|
||||
|
||||
args[0] = '\0';
|
||||
|
||||
for(i = fa; i < cmdargc; i++) {
|
||||
if(i != fa)
|
||||
strcat(args, " ");
|
||||
strcat(args, cmdargv[i]);
|
||||
}
|
||||
|
||||
return(DOcommand(cmd, args));
|
||||
}
|
||||
|
||||
int DOquote()
|
||||
{
|
||||
return(docmdargs(cmdargv[1], 2));
|
||||
}
|
||||
|
||||
int DOsite()
|
||||
{
|
||||
return(docmdargs("SITE", 1));
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/* other.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 01/25/96 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*/
|
||||
|
||||
void FTPinit(void);
|
||||
int DOpass(void);
|
||||
int DOuser(void);
|
||||
int DOnoop(void);
|
||||
int DOpassive(void);
|
||||
int DOsyst(void);
|
||||
int DOremotehelp(void);
|
||||
int DOquote(void);
|
||||
int DOsite(void);
|
|
@ -1,305 +0,0 @@
|
|||
/* xfer.c Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*
|
||||
* 03/14/00 Initial Release Michael Temari, <Michael@TemWare.Com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <utime.h>
|
||||
#include <net/hton.h>
|
||||
|
||||
#include "ftp.h"
|
||||
#include "xfer.h"
|
||||
|
||||
static int asciisend(int fd, int fdout);
|
||||
static int binarysend(int fd, int fdout);
|
||||
static int asciirecv(int fd, int fdin);
|
||||
static int binaryrecv(int fd, int fdin);
|
||||
|
||||
#if (__WORD_SIZE == 4)
|
||||
static char buffer[8192];
|
||||
static char bufout[8192];
|
||||
#else
|
||||
static char buffer[2048];
|
||||
static char bufout[2048];
|
||||
#endif
|
||||
|
||||
static int asciisend(fd, fdout)
|
||||
int fd;
|
||||
int fdout;
|
||||
{
|
||||
int s;
|
||||
char c;
|
||||
char *p;
|
||||
char *op, *ope;
|
||||
unsigned long total=0L;
|
||||
char block[3];
|
||||
|
||||
if(atty) {
|
||||
printf("Sent ");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
op = bufout;
|
||||
ope = bufout + sizeof(bufout) - 3;
|
||||
|
||||
while((s = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
total += (long)s;
|
||||
p = buffer;
|
||||
while(s-- > 0) {
|
||||
c = *p++;
|
||||
if(c == '\n') {
|
||||
*op++ = '\r';
|
||||
total++;
|
||||
}
|
||||
*op++ = c;
|
||||
if(op >= ope) {
|
||||
if(mode == MODE_B) {
|
||||
block[0] = '\0';
|
||||
*(u16_t *)&block[1] = htons(op - bufout);
|
||||
write(fdout, block, sizeof(block));
|
||||
}
|
||||
write(fdout, bufout, op - bufout);
|
||||
op = bufout;
|
||||
}
|
||||
}
|
||||
if(atty) {
|
||||
printf("%8lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
if(op > bufout) {
|
||||
if(mode == MODE_B) {
|
||||
block[0] = MODE_B_EOF;
|
||||
*(u16_t *)&block[1] = htons(op - bufout);
|
||||
write(fdout, block, sizeof(block));
|
||||
}
|
||||
write(fdout, bufout, op - bufout);
|
||||
} else if(mode == MODE_B) {
|
||||
block[0] = MODE_B_EOF;
|
||||
*(u16_t *)&block[1] = htons(0);
|
||||
write(fdout, block, sizeof(block));
|
||||
s = 0;
|
||||
}
|
||||
if(atty) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
static int binarysend(fd, fdout)
|
||||
int fd;
|
||||
int fdout;
|
||||
{
|
||||
int s;
|
||||
unsigned long total=0L;
|
||||
char block[3];
|
||||
|
||||
if(atty) {
|
||||
printf("Sent ");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
while((s = read(fd, buffer, sizeof(buffer))) > 0) {
|
||||
if(mode == MODE_B) {
|
||||
block[0] = MODE_B_EOF;
|
||||
*(u16_t *)&block[1] = htons(s);
|
||||
write(fdout, block, sizeof(block));
|
||||
}
|
||||
write(fdout, buffer, s);
|
||||
total += (long)s;
|
||||
if(atty) {
|
||||
printf("%8lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
if(mode == MODE_B) {
|
||||
block[0] = MODE_B_EOF;
|
||||
*(u16_t *)&block[1] = htons(0);
|
||||
write(fdout, block, sizeof(block));
|
||||
s = 0;
|
||||
}
|
||||
if(atty) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
return(s);
|
||||
}
|
||||
|
||||
int sendfile(fd, fdout)
|
||||
int fd;
|
||||
int fdout;
|
||||
{
|
||||
int s;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_A:
|
||||
s = asciisend(fd, fdout);
|
||||
break;
|
||||
default:
|
||||
s = binarysend(fd, fdout);
|
||||
}
|
||||
|
||||
if(s < 0)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int asciirecv(fd, fdin)
|
||||
int fd;
|
||||
int fdin;
|
||||
{
|
||||
int s;
|
||||
int gotcr;
|
||||
char c;
|
||||
char *p;
|
||||
char *op, *ope;
|
||||
unsigned long total=0L;
|
||||
char block[3];
|
||||
unsigned short cnt;
|
||||
|
||||
if(isatty && fd > 2) {
|
||||
printf("Received ");
|
||||
fflush(stdout);
|
||||
}
|
||||
gotcr = 0;
|
||||
op = bufout; ope = bufout + sizeof(bufout) - 3;
|
||||
cnt = 0;
|
||||
while(1) {
|
||||
if(mode != MODE_B)
|
||||
cnt = sizeof(buffer);
|
||||
else
|
||||
if(cnt == 0) {
|
||||
s = read(fdin, block, sizeof(block));
|
||||
cnt = ntohs(*(u16_t *)&block[1]);
|
||||
s = 0;
|
||||
if(cnt == 0 && block[0] & MODE_B_EOF)
|
||||
break;
|
||||
}
|
||||
s = read(fdin, buffer, cnt > sizeof(buffer) ? sizeof(buffer) : cnt);
|
||||
if(s <= 0) break;
|
||||
cnt -= s;
|
||||
total += (long)s;
|
||||
p = buffer;
|
||||
while(s-- > 0) {
|
||||
c = *p++;
|
||||
if(gotcr) {
|
||||
gotcr = 0;
|
||||
if(c != '\n')
|
||||
*op++ = '\r';
|
||||
}
|
||||
if(c == '\r')
|
||||
gotcr = 1;
|
||||
else
|
||||
*op++ = c;
|
||||
if(op >= ope) {
|
||||
write(fd, bufout, op - bufout);
|
||||
op = bufout;
|
||||
}
|
||||
}
|
||||
if(atty && fd > 2) {
|
||||
printf("%8lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
|
||||
fflush(stdout);
|
||||
}
|
||||
if(cnt == 0 && mode == MODE_B && block[0] & MODE_B_EOF) {
|
||||
s = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(gotcr)
|
||||
*op++ = '\r';
|
||||
if(op > bufout)
|
||||
write(fd, bufout, op - bufout);
|
||||
if(atty && fd > 2) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
if((mode == MODE_B && cnt != 0) || s != 0)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int binaryrecv(fd, fdin)
|
||||
int fd;
|
||||
int fdin;
|
||||
{
|
||||
int s;
|
||||
unsigned long total=0L;
|
||||
char block[3];
|
||||
unsigned short cnt;
|
||||
|
||||
if(atty && fd > 2) {
|
||||
printf("Received ");
|
||||
fflush(stdout);
|
||||
}
|
||||
cnt = 0;
|
||||
while(1) {
|
||||
if(mode != MODE_B)
|
||||
cnt = sizeof(buffer);
|
||||
else
|
||||
if(cnt == 0) {
|
||||
s = read(fdin, block, sizeof(block));
|
||||
cnt = ntohs(*(u16_t *)&block[1]);
|
||||
s = 0;
|
||||
if(cnt == 0 && block[0] & MODE_B_EOF)
|
||||
break;
|
||||
}
|
||||
s = read(fdin, buffer, cnt > sizeof(buffer) ? sizeof(buffer) : cnt);
|
||||
if(s <= 0) break;
|
||||
cnt -= s;
|
||||
total += (long)s;
|
||||
write(fd, buffer, s);
|
||||
if(atty && fd > 2) {
|
||||
printf("%8lu bytes\b\b\b\b\b\b\b\b\b\b\b\b\b\b", total);
|
||||
fflush(stdout);
|
||||
}
|
||||
if(cnt == 0 && mode == MODE_B && block[0] & MODE_B_EOF) {
|
||||
s = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(atty && fd > 2) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
if((mode == MODE_B && cnt != 0) || s != 0)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
int recvfile(fd, fdin)
|
||||
int fd;
|
||||
int fdin;
|
||||
{
|
||||
int s;
|
||||
|
||||
switch(type) {
|
||||
case TYPE_A:
|
||||
s = asciirecv(fd, fdin);
|
||||
break;
|
||||
default:
|
||||
s = binaryrecv(fd, fdin);
|
||||
}
|
||||
|
||||
if(s < 0)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
/* xfer.h Copyright 1992-2000 by Michael Temari All Rights Reserved
|
||||
*
|
||||
* This file is part of ftp.
|
||||
*
|
||||
*/
|
||||
|
||||
int recvfile(int fd, int fdin);
|
||||
int sendfile(int fd, int fdout);
|
|
@ -131,6 +131,7 @@
|
|||
2012/10/17 12:00:00,usr.bin/ctags
|
||||
2011/09/01 13:37:33,usr.bin/du
|
||||
2013/03/22 12:00:00,usr.bin/from
|
||||
2013/04/05 12:00:00,usr.bin/ftp
|
||||
2013/03/18 12:00:00,usr.bin/head
|
||||
2012/10/17 12:00:00,usr.bin/genassym
|
||||
2013/03/09 12:00:00,usr.bin/getopt
|
||||
|
|
|
@ -10,7 +10,7 @@ SUBDIR= \
|
|||
col ctags \
|
||||
du \
|
||||
\
|
||||
from \
|
||||
from ftp \
|
||||
genassym getopt head \
|
||||
indent infocmp join \
|
||||
ldd \
|
||||
|
|
40
usr.bin/ftp/Makefile
Normal file
40
usr.bin/ftp/Makefile
Normal file
|
@ -0,0 +1,40 @@
|
|||
# $NetBSD: Makefile,v 1.36 2012/12/21 18:07:36 christos Exp $
|
||||
# from: @(#)Makefile 8.2 (Berkeley) 4/3/94
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
USE_FORT?= yes # network client
|
||||
|
||||
PROG= ftp
|
||||
SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \
|
||||
progressbar.c ruserpass.c util.c
|
||||
|
||||
# Uncomment the following to provide defaults for gate-ftp operation
|
||||
#
|
||||
#CPPFLAGS+=-DGATE_SERVER=\"ftp-gw.host\" # -DGATE_PORT=21
|
||||
|
||||
.if defined(__MINIX)
|
||||
CPPFLAGS+= -DDIRENT_MISSING_D_NAMLEN
|
||||
.endif # defined (__MINIX)
|
||||
|
||||
.if defined(SMALLPROG)
|
||||
CPPFLAGS+=-DNO_EDITCOMPLETE -DNO_ABOUT -DNO_AUTH -DNO_HELP -DNO_STATUS -DNO_DEBUG -DNO_USAGE
|
||||
.else
|
||||
LDADD+= -ledit -lterminfo
|
||||
DPADD+= ${LIBEDIT} ${LIBTERMINFO}
|
||||
.if (${MKCRYPTO} != "no")
|
||||
CPPFLAGS+= -DWITH_SSL
|
||||
SRCS+=ssl.c
|
||||
LDADD+= -lssl -lcrypto
|
||||
DPADD+= ${LIBSSL} ${LIBCRYPTO}
|
||||
.endif
|
||||
.endif
|
||||
|
||||
.if (!defined(SMALLPROG) || defined(SMALLPROG_INET6)) && (${USE_INET6} != "no")
|
||||
CPPFLAGS+= -DINET6
|
||||
.endif
|
||||
|
||||
cmds.o fetch.o: version.h
|
||||
main.o: ftp_var.h
|
||||
|
||||
.include <bsd.prog.mk>
|
2795
usr.bin/ftp/cmds.c
Normal file
2795
usr.bin/ftp/cmds.c
Normal file
File diff suppressed because it is too large
Load diff
307
usr.bin/ftp/cmdtab.c
Normal file
307
usr.bin/ftp/cmdtab.c
Normal file
|
@ -0,0 +1,307 @@
|
|||
/* $NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: cmdtab.c,v 1.52 2012/12/22 16:57:09 christos Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "ftp_var.h"
|
||||
|
||||
/*
|
||||
* User FTP -- Command Tables.
|
||||
*/
|
||||
|
||||
#define HSTR static const char
|
||||
|
||||
#ifndef NO_HELP
|
||||
HSTR accounthelp[] = "send account command to remote server";
|
||||
HSTR appendhelp[] = "append to a file";
|
||||
HSTR asciihelp[] = "set ascii transfer type";
|
||||
HSTR beephelp[] = "beep when command completed";
|
||||
HSTR binaryhelp[] = "set binary transfer type";
|
||||
HSTR casehelp[] = "toggle mget upper/lower case id mapping";
|
||||
HSTR cdhelp[] = "change remote working directory";
|
||||
HSTR cduphelp[] = "change remote working directory to parent directory";
|
||||
HSTR chmodhelp[] = "change file permissions of remote file";
|
||||
HSTR connecthelp[] = "connect to remote ftp server";
|
||||
HSTR crhelp[] = "toggle carriage return stripping on ascii gets";
|
||||
HSTR debughelp[] = "toggle/set debugging mode";
|
||||
HSTR deletehelp[] = "delete remote file";
|
||||
HSTR disconhelp[] = "terminate ftp session";
|
||||
HSTR domachelp[] = "execute macro";
|
||||
HSTR edithelp[] = "toggle command line editing";
|
||||
HSTR epsvhelp[] = "toggle use of EPSV/EPRT on both IPv4 and IPV6 ftp";
|
||||
HSTR epsv4help[] = "toggle use of EPSV/EPRT on IPv4 ftp";
|
||||
HSTR epsv6help[] = "toggle use of EPSV/EPRT on IPv6 ftp";
|
||||
HSTR feathelp[] = "show FEATures supported by remote system";
|
||||
HSTR formhelp[] = "set file transfer format";
|
||||
HSTR gatehelp[] = "toggle gate-ftp; specify host[:port] to change proxy";
|
||||
HSTR globhelp[] = "toggle metacharacter expansion of local file names";
|
||||
HSTR hashhelp[] = "toggle printing `#' marks; specify number to set size";
|
||||
HSTR helphelp[] = "print local help information";
|
||||
HSTR idlehelp[] = "get (set) idle timer on remote side";
|
||||
HSTR lcdhelp[] = "change local working directory";
|
||||
HSTR lpagehelp[] = "view a local file through your pager";
|
||||
HSTR lpwdhelp[] = "print local working directory";
|
||||
HSTR lshelp[] = "list contents of remote path";
|
||||
HSTR macdefhelp[] = "define a macro";
|
||||
HSTR mdeletehelp[] = "delete multiple files";
|
||||
HSTR mgethelp[] = "get multiple files";
|
||||
HSTR mregethelp[] = "get multiple files restarting at end of local file";
|
||||
HSTR fgethelp[] = "get files using a localfile as a source of names";
|
||||
HSTR mkdirhelp[] = "make directory on the remote machine";
|
||||
HSTR mlshelp[] = "list contents of multiple remote directories";
|
||||
HSTR mlsdhelp[] = "list contents of remote directory in a machine "
|
||||
"parsable form";
|
||||
HSTR mlsthelp[] = "list remote path in a machine parsable form";
|
||||
HSTR modehelp[] = "set file transfer mode";
|
||||
HSTR modtimehelp[] = "show last modification time of remote file";
|
||||
HSTR mputhelp[] = "send multiple files";
|
||||
HSTR newerhelp[] = "get file if remote file is newer than local file ";
|
||||
HSTR nmaphelp[] = "set templates for default file name mapping";
|
||||
HSTR ntranshelp[] = "set translation table for default file name mapping";
|
||||
HSTR optshelp[] = "show or set options for remote commands";
|
||||
HSTR pagehelp[] = "view a remote file through your pager";
|
||||
HSTR passivehelp[] = "toggle use of passive transfer mode";
|
||||
HSTR plshelp[] = "list contents of remote path through your pager";
|
||||
HSTR pmlsdhelp[] = "list contents of remote directory in a machine "
|
||||
"parsable form through your pager";
|
||||
HSTR porthelp[] = "toggle use of PORT/LPRT cmd for each data connection";
|
||||
HSTR preservehelp[] ="toggle preservation of modification time of "
|
||||
"retrieved files";
|
||||
HSTR progresshelp[] ="toggle transfer progress meter";
|
||||
HSTR prompthelp[] = "force interactive prompting on multiple commands";
|
||||
HSTR proxyhelp[] = "issue command on alternate connection";
|
||||
HSTR pwdhelp[] = "print working directory on remote machine";
|
||||
HSTR quithelp[] = "terminate ftp session and exit";
|
||||
HSTR quotehelp[] = "send arbitrary ftp command";
|
||||
HSTR ratehelp[] = "set transfer rate limit (in bytes/second)";
|
||||
HSTR receivehelp[] = "receive file";
|
||||
HSTR regethelp[] = "get file restarting at end of local file";
|
||||
HSTR remotehelp[] = "get help from remote server";
|
||||
HSTR renamehelp[] = "rename file";
|
||||
HSTR resethelp[] = "clear queued command replies";
|
||||
HSTR restarthelp[]= "restart file transfer at bytecount";
|
||||
HSTR rmdirhelp[] = "remove directory on the remote machine";
|
||||
HSTR rmtstatushelp[]="show status of remote machine";
|
||||
HSTR runiquehelp[] = "toggle store unique for local files";
|
||||
HSTR sendhelp[] = "send one file";
|
||||
HSTR sethelp[] = "set or display options";
|
||||
HSTR shellhelp[] = "escape to the shell";
|
||||
HSTR sitehelp[] = "send site specific command to remote server\n"
|
||||
"\t\tTry \"rhelp site\" or \"site help\" "
|
||||
"for more information";
|
||||
HSTR sizecmdhelp[] = "show size of remote file";
|
||||
HSTR statushelp[] = "show current status";
|
||||
HSTR structhelp[] = "set file transfer structure";
|
||||
HSTR suniquehelp[] = "toggle store unique on remote machine";
|
||||
HSTR systemhelp[] = "show remote system type";
|
||||
HSTR tenexhelp[] = "set tenex file transfer type";
|
||||
HSTR tracehelp[] = "toggle packet tracing";
|
||||
HSTR typehelp[] = "set file transfer type";
|
||||
HSTR umaskhelp[] = "get (set) umask on remote side";
|
||||
HSTR unsethelp[] = "unset an option";
|
||||
HSTR usagehelp[] = "show command usage";
|
||||
HSTR userhelp[] = "send new user information";
|
||||
HSTR verbosehelp[] = "toggle verbose mode";
|
||||
HSTR xferbufhelp[] = "set socket send/receive buffer size";
|
||||
#endif
|
||||
|
||||
HSTR empty[] = "";
|
||||
|
||||
#ifdef NO_HELP
|
||||
#define H(x) empty
|
||||
#else
|
||||
#define H(x) x
|
||||
#endif
|
||||
|
||||
#ifdef NO_EDITCOMPLETE
|
||||
#define CMPL(x)
|
||||
#define CMPL0
|
||||
#else /* !NO_EDITCOMPLETE */
|
||||
#define CMPL(x) #x,
|
||||
#define CMPL0 empty,
|
||||
#endif /* !NO_EDITCOMPLETE */
|
||||
|
||||
struct cmd cmdtab[] = {
|
||||
{ "!", H(shellhelp), 0, 0, 0, CMPL0 shell },
|
||||
{ "$", H(domachelp), 1, 0, 0, CMPL0 domacro },
|
||||
{ "account", H(accounthelp), 0, 1, 1, CMPL0 account},
|
||||
{ "append", H(appendhelp), 1, 1, 1, CMPL(lr) put },
|
||||
{ "ascii", H(asciihelp), 0, 1, 1, CMPL0 setascii },
|
||||
{ "bell", H(beephelp), 0, 0, 0, CMPL0 setbell },
|
||||
{ "binary", H(binaryhelp), 0, 1, 1, CMPL0 setbinary },
|
||||
{ "bye", H(quithelp), 0, 0, 0, CMPL0 quit },
|
||||
{ "case", H(casehelp), 0, 0, 1, CMPL0 setcase },
|
||||
{ "cd", H(cdhelp), 0, 1, 1, CMPL(r) cd },
|
||||
{ "cdup", H(cduphelp), 0, 1, 1, CMPL0 cdup },
|
||||
{ "chmod", H(chmodhelp), 0, 1, 1, CMPL(nr) do_chmod },
|
||||
{ "close", H(disconhelp), 0, 1, 1, CMPL0 disconnect },
|
||||
{ "cr", H(crhelp), 0, 0, 0, CMPL0 setcr },
|
||||
{ "debug", H(debughelp), 0, 0, 0, CMPL0 setdebug },
|
||||
{ "delete", H(deletehelp), 0, 1, 1, CMPL(r) delete },
|
||||
{ "dir", H(lshelp), 1, 1, 1, CMPL(rl) ls },
|
||||
{ "disconnect", H(disconhelp), 0, 1, 1, CMPL0 disconnect },
|
||||
{ "edit", H(edithelp), 0, 0, 0, CMPL0 setedit },
|
||||
{ "epsv", H(epsvhelp), 0, 0, 0, CMPL0 setepsv },
|
||||
{ "epsv4", H(epsv4help), 0, 0, 0, CMPL0 setepsv4 },
|
||||
{ "epsv6", H(epsv6help), 0, 0, 0, CMPL0 setepsv6 },
|
||||
{ "exit", H(quithelp), 0, 0, 0, CMPL0 quit },
|
||||
{ "features", H(feathelp), 0, 1, 1, CMPL0 feat },
|
||||
{ "fget", H(fgethelp), 1, 1, 1, CMPL(l) fget },
|
||||
{ "form", H(formhelp), 0, 1, 1, CMPL0 setform },
|
||||
{ "ftp", H(connecthelp), 0, 0, 1, CMPL0 setpeer },
|
||||
{ "gate", H(gatehelp), 0, 0, 0, CMPL0 setgate },
|
||||
{ "get", H(receivehelp), 1, 1, 1, CMPL(rl) get },
|
||||
{ "glob", H(globhelp), 0, 0, 0, CMPL0 setglob },
|
||||
{ "hash", H(hashhelp), 0, 0, 0, CMPL0 sethash },
|
||||
{ "help", H(helphelp), 0, 0, 1, CMPL(C) help },
|
||||
{ "idle", H(idlehelp), 0, 1, 1, CMPL0 idlecmd },
|
||||
{ "image", H(binaryhelp), 0, 1, 1, CMPL0 setbinary },
|
||||
{ "lcd", H(lcdhelp), 0, 0, 0, CMPL(l) lcd },
|
||||
{ "less", H(pagehelp), 1, 1, 1, CMPL(r) page },
|
||||
{ "lpage", H(lpagehelp), 0, 0, 0, CMPL(l) lpage },
|
||||
{ "lpwd", H(lpwdhelp), 0, 0, 0, CMPL0 lpwd },
|
||||
{ "ls", H(lshelp), 1, 1, 1, CMPL(rl) ls },
|
||||
{ "macdef", H(macdefhelp), 0, 0, 0, CMPL0 macdef },
|
||||
{ "mdelete", H(mdeletehelp), 1, 1, 1, CMPL(R) mdelete },
|
||||
{ "mdir", H(mlshelp), 1, 1, 1, CMPL(R) mls },
|
||||
{ "mget", H(mgethelp), 1, 1, 1, CMPL(R) mget },
|
||||
{ "mkdir", H(mkdirhelp), 0, 1, 1, CMPL(r) makedir },
|
||||
{ "mls", H(mlshelp), 1, 1, 1, CMPL(R) mls },
|
||||
{ "mlsd", H(mlsdhelp), 1, 1, 1, CMPL(r) ls },
|
||||
{ "mlst", H(mlsthelp), 1, 1, 1, CMPL(r) mlst },
|
||||
{ "mode", H(modehelp), 0, 1, 1, CMPL0 setftmode },
|
||||
{ "modtime", H(modtimehelp), 0, 1, 1, CMPL(r) modtime },
|
||||
{ "more", H(pagehelp), 1, 1, 1, CMPL(r) page },
|
||||
{ "mput", H(mputhelp), 1, 1, 1, CMPL(L) mput },
|
||||
{ "mreget", H(mregethelp), 1, 1, 1, CMPL(R) mget },
|
||||
{ "msend", H(mputhelp), 1, 1, 1, CMPL(L) mput },
|
||||
{ "newer", H(newerhelp), 1, 1, 1, CMPL(r) newer },
|
||||
{ "nlist", H(lshelp), 1, 1, 1, CMPL(rl) ls },
|
||||
{ "nmap", H(nmaphelp), 0, 0, 1, CMPL0 setnmap },
|
||||
{ "ntrans", H(ntranshelp), 0, 0, 1, CMPL0 setntrans },
|
||||
{ "open", H(connecthelp), 0, 0, 1, CMPL0 setpeer },
|
||||
{ "page", H(pagehelp), 1, 1, 1, CMPL(r) page },
|
||||
{ "passive", H(passivehelp), 0, 0, 0, CMPL0 setpassive },
|
||||
{ "pdir", H(plshelp), 1, 1, 1, CMPL(r) ls },
|
||||
{ "pls", H(plshelp), 1, 1, 1, CMPL(r) ls },
|
||||
{ "pmlsd", H(pmlsdhelp), 1, 1, 1, CMPL(r) ls },
|
||||
{ "preserve", H(preservehelp),0, 0, 0, CMPL0 setpreserve },
|
||||
{ "progress", H(progresshelp),0, 0, 0, CMPL0 setprogress },
|
||||
{ "prompt", H(prompthelp), 0, 0, 0, CMPL0 setprompt },
|
||||
{ "proxy", H(proxyhelp), 0, 0, 1, CMPL(c) doproxy },
|
||||
{ "put", H(sendhelp), 1, 1, 1, CMPL(lr) put },
|
||||
{ "pwd", H(pwdhelp), 0, 1, 1, CMPL0 pwd },
|
||||
{ "quit", H(quithelp), 0, 0, 0, CMPL0 quit },
|
||||
{ "quote", H(quotehelp), 1, 1, 1, CMPL0 quote },
|
||||
{ "rate", H(ratehelp), 0, 0, 0, CMPL0 setrate },
|
||||
{ "rcvbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf },
|
||||
{ "recv", H(receivehelp), 1, 1, 1, CMPL(rl) get },
|
||||
{ "reget", H(regethelp), 1, 1, 1, CMPL(rl) reget },
|
||||
{ "remopts", H(optshelp), 0, 1, 1, CMPL0 opts },
|
||||
{ "rename", H(renamehelp), 0, 1, 1, CMPL(rr) renamefile },
|
||||
{ "reset", H(resethelp), 0, 1, 1, CMPL0 reset },
|
||||
{ "restart", H(restarthelp), 1, 1, 1, CMPL0 restart },
|
||||
{ "rhelp", H(remotehelp), 0, 1, 1, CMPL0 rmthelp },
|
||||
{ "rmdir", H(rmdirhelp), 0, 1, 1, CMPL(r) removedir },
|
||||
{ "rstatus", H(rmtstatushelp),0, 1, 1, CMPL(r) rmtstatus },
|
||||
{ "runique", H(runiquehelp), 0, 0, 1, CMPL0 setrunique },
|
||||
{ "send", H(sendhelp), 1, 1, 1, CMPL(lr) put },
|
||||
{ "sendport", H(porthelp), 0, 0, 0, CMPL0 setport },
|
||||
{ "set", H(sethelp), 0, 0, 0, CMPL(o) setoption },
|
||||
{ "site", H(sitehelp), 0, 1, 1, CMPL0 site },
|
||||
{ "size", H(sizecmdhelp), 1, 1, 1, CMPL(r) sizecmd },
|
||||
{ "sndbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf },
|
||||
{ "status", H(statushelp), 0, 0, 1, CMPL0 status },
|
||||
{ "struct", H(structhelp), 0, 1, 1, CMPL0 setstruct },
|
||||
{ "sunique", H(suniquehelp), 0, 0, 1, CMPL0 setsunique },
|
||||
{ "system", H(systemhelp), 0, 1, 1, CMPL0 syst },
|
||||
{ "tenex", H(tenexhelp), 0, 1, 1, CMPL0 settenex },
|
||||
{ "throttle", H(ratehelp), 0, 0, 0, CMPL0 setrate },
|
||||
{ "trace", H(tracehelp), 0, 0, 0, CMPL0 settrace },
|
||||
{ "type", H(typehelp), 0, 1, 1, CMPL0 settype },
|
||||
{ "umask", H(umaskhelp), 0, 1, 1, CMPL0 do_umask },
|
||||
{ "unset", H(unsethelp), 0, 0, 0, CMPL(o) unsetoption },
|
||||
{ "usage", H(usagehelp), 0, 0, 1, CMPL(C) help },
|
||||
{ "user", H(userhelp), 0, 1, 1, CMPL0 user },
|
||||
{ "verbose", H(verbosehelp), 0, 0, 0, CMPL0 setverbose },
|
||||
{ "xferbuf", H(xferbufhelp), 0, 0, 0, CMPL0 setxferbuf },
|
||||
{ "?", H(helphelp), 0, 0, 1, CMPL(C) help },
|
||||
{ NULL, NULL, 0, 0, 0, CMPL0 NULL },
|
||||
};
|
||||
|
||||
struct option optiontab[] = {
|
||||
{ "anonpass", NULL },
|
||||
{ "ftp_proxy", NULL },
|
||||
{ "http_proxy", NULL },
|
||||
{ "https_proxy",NULL },
|
||||
{ "no_proxy", NULL },
|
||||
{ "pager", NULL },
|
||||
{ "prompt", NULL },
|
||||
{ "rprompt", NULL },
|
||||
{ NULL, NULL },
|
||||
};
|
432
usr.bin/ftp/complete.c
Normal file
432
usr.bin/ftp/complete.c
Normal file
|
@ -0,0 +1,432 @@
|
|||
/* $NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: complete.c,v 1.46 2009/04/12 10:18:52 lukem Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* FTP user program - command and file completion routines
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ftp_var.h"
|
||||
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
|
||||
static int comparstr (const void *, const void *);
|
||||
static unsigned char complete_ambiguous (char *, int, StringList *);
|
||||
static unsigned char complete_command (char *, int);
|
||||
static unsigned char complete_local (char *, int);
|
||||
static unsigned char complete_option (char *, int);
|
||||
static unsigned char complete_remote (char *, int);
|
||||
|
||||
static int
|
||||
comparstr(const void *a, const void *b)
|
||||
{
|
||||
return (strcmp(*(const char * const *)a, *(const char * const *)b));
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if complete is ambiguous. If unique, insert.
|
||||
* If no choices, error. If unambiguous prefix, insert that.
|
||||
* Otherwise, list choices. words is assumed to be filtered
|
||||
* to only contain possible choices.
|
||||
* Args:
|
||||
* word word which started the match
|
||||
* list list by default
|
||||
* words stringlist containing possible matches
|
||||
* Returns a result as per el_set(EL_ADDFN, ...)
|
||||
*/
|
||||
static unsigned char
|
||||
complete_ambiguous(char *word, int list, StringList *words)
|
||||
{
|
||||
char insertstr[MAXPATHLEN];
|
||||
char *lastmatch, *p;
|
||||
size_t i, j;
|
||||
size_t matchlen, wordlen;
|
||||
|
||||
wordlen = strlen(word);
|
||||
if (words->sl_cur == 0)
|
||||
return (CC_ERROR); /* no choices available */
|
||||
|
||||
if (words->sl_cur == 1) { /* only once choice available */
|
||||
p = words->sl_str[0] + wordlen;
|
||||
if (*p == '\0') /* at end of word? */
|
||||
return (CC_REFRESH);
|
||||
ftpvis(insertstr, sizeof(insertstr), p, strlen(p));
|
||||
if (el_insertstr(el, insertstr) == -1)
|
||||
return (CC_ERROR);
|
||||
else
|
||||
return (CC_REFRESH);
|
||||
}
|
||||
|
||||
if (!list) {
|
||||
matchlen = 0;
|
||||
lastmatch = words->sl_str[0];
|
||||
matchlen = strlen(lastmatch);
|
||||
for (i = 1 ; i < words->sl_cur ; i++) {
|
||||
for (j = wordlen ; j < strlen(words->sl_str[i]); j++)
|
||||
if (lastmatch[j] != words->sl_str[i][j])
|
||||
break;
|
||||
if (j < matchlen)
|
||||
matchlen = j;
|
||||
}
|
||||
if (matchlen > wordlen) {
|
||||
ftpvis(insertstr, sizeof(insertstr),
|
||||
lastmatch + wordlen, matchlen - wordlen);
|
||||
if (el_insertstr(el, insertstr) == -1)
|
||||
return (CC_ERROR);
|
||||
else
|
||||
return (CC_REFRESH_BEEP);
|
||||
}
|
||||
}
|
||||
|
||||
putc('\n', ttyout);
|
||||
qsort(words->sl_str, words->sl_cur, sizeof(char *), comparstr);
|
||||
list_vertical(words);
|
||||
return (CC_REDISPLAY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete a command
|
||||
*/
|
||||
static unsigned char
|
||||
complete_command(char *word, int list)
|
||||
{
|
||||
struct cmd *c;
|
||||
StringList *words;
|
||||
size_t wordlen;
|
||||
unsigned char rv;
|
||||
|
||||
words = ftp_sl_init();
|
||||
wordlen = strlen(word);
|
||||
|
||||
for (c = cmdtab; c->c_name != NULL; c++) {
|
||||
if (wordlen > strlen(c->c_name))
|
||||
continue;
|
||||
if (strncmp(word, c->c_name, wordlen) == 0)
|
||||
ftp_sl_add(words, ftp_strdup(c->c_name));
|
||||
}
|
||||
|
||||
rv = complete_ambiguous(word, list, words);
|
||||
if (rv == CC_REFRESH) {
|
||||
if (el_insertstr(el, " ") == -1)
|
||||
rv = CC_ERROR;
|
||||
}
|
||||
sl_free(words, 1);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete a local file
|
||||
*/
|
||||
static unsigned char
|
||||
complete_local(char *word, int list)
|
||||
{
|
||||
StringList *words;
|
||||
char dir[MAXPATHLEN];
|
||||
char *file;
|
||||
DIR *dd;
|
||||
struct dirent *dp;
|
||||
unsigned char rv;
|
||||
size_t len;
|
||||
|
||||
if ((file = strrchr(word, '/')) == NULL) {
|
||||
dir[0] = '.';
|
||||
dir[1] = '\0';
|
||||
file = word;
|
||||
} else {
|
||||
if (file == word) {
|
||||
dir[0] = '/';
|
||||
dir[1] = '\0';
|
||||
} else
|
||||
(void)strlcpy(dir, word, file - word + 1);
|
||||
file++;
|
||||
}
|
||||
if (dir[0] == '~') {
|
||||
char *p;
|
||||
|
||||
if ((p = globulize(dir)) == NULL)
|
||||
return (CC_ERROR);
|
||||
(void)strlcpy(dir, p, sizeof(dir));
|
||||
free(p);
|
||||
}
|
||||
|
||||
if ((dd = opendir(dir)) == NULL)
|
||||
return (CC_ERROR);
|
||||
|
||||
words = ftp_sl_init();
|
||||
len = strlen(file);
|
||||
|
||||
for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) {
|
||||
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
|
||||
continue;
|
||||
|
||||
#if defined(DIRENT_MISSING_D_NAMLEN)
|
||||
if (len > strlen(dp->d_name))
|
||||
continue;
|
||||
#else
|
||||
if (len > dp->d_namlen)
|
||||
continue;
|
||||
#endif
|
||||
if (strncmp(file, dp->d_name, len) == 0) {
|
||||
char *tcp;
|
||||
|
||||
tcp = ftp_strdup(dp->d_name);
|
||||
ftp_sl_add(words, tcp);
|
||||
}
|
||||
}
|
||||
closedir(dd);
|
||||
|
||||
rv = complete_ambiguous(file, list, words);
|
||||
if (rv == CC_REFRESH) {
|
||||
struct stat sb;
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
(void)strlcpy(path, dir, sizeof(path));
|
||||
(void)strlcat(path, "/", sizeof(path));
|
||||
(void)strlcat(path, words->sl_str[0], sizeof(path));
|
||||
|
||||
if (stat(path, &sb) >= 0) {
|
||||
char suffix[2] = " ";
|
||||
|
||||
if (S_ISDIR(sb.st_mode))
|
||||
suffix[0] = '/';
|
||||
if (el_insertstr(el, suffix) == -1)
|
||||
rv = CC_ERROR;
|
||||
}
|
||||
}
|
||||
sl_free(words, 1);
|
||||
return (rv);
|
||||
}
|
||||
/*
|
||||
* Complete an option
|
||||
*/
|
||||
static unsigned char
|
||||
complete_option(char *word, int list)
|
||||
{
|
||||
struct option *o;
|
||||
StringList *words;
|
||||
size_t wordlen;
|
||||
unsigned char rv;
|
||||
|
||||
words = ftp_sl_init();
|
||||
wordlen = strlen(word);
|
||||
|
||||
for (o = optiontab; o->name != NULL; o++) {
|
||||
if (wordlen > strlen(o->name))
|
||||
continue;
|
||||
if (strncmp(word, o->name, wordlen) == 0)
|
||||
ftp_sl_add(words, ftp_strdup(o->name));
|
||||
}
|
||||
|
||||
rv = complete_ambiguous(word, list, words);
|
||||
if (rv == CC_REFRESH) {
|
||||
if (el_insertstr(el, " ") == -1)
|
||||
rv = CC_ERROR;
|
||||
}
|
||||
sl_free(words, 1);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Complete a remote file
|
||||
*/
|
||||
static unsigned char
|
||||
complete_remote(char *word, int list)
|
||||
{
|
||||
static StringList *dirlist;
|
||||
static char lastdir[MAXPATHLEN];
|
||||
StringList *words;
|
||||
char dir[MAXPATHLEN];
|
||||
char *file, *cp;
|
||||
size_t i;
|
||||
unsigned char rv;
|
||||
char cmdbuf[MAX_C_NAME];
|
||||
char *dummyargv[3] = { NULL, NULL, NULL };
|
||||
|
||||
(void)strlcpy(cmdbuf, "complete", sizeof(cmdbuf));
|
||||
dummyargv[0] = cmdbuf;
|
||||
dummyargv[1] = dir;
|
||||
|
||||
if ((file = strrchr(word, '/')) == NULL) {
|
||||
dir[0] = '\0';
|
||||
file = word;
|
||||
} else {
|
||||
cp = file;
|
||||
while (*cp == '/' && cp > word)
|
||||
cp--;
|
||||
(void)strlcpy(dir, word, cp - word + 2);
|
||||
file++;
|
||||
}
|
||||
|
||||
if (dirchange || dirlist == NULL ||
|
||||
strcmp(dir, lastdir) != 0) { /* dir not cached */
|
||||
const char *emesg;
|
||||
|
||||
if (dirlist != NULL)
|
||||
sl_free(dirlist, 1);
|
||||
dirlist = ftp_sl_init();
|
||||
|
||||
mflag = 1;
|
||||
emesg = NULL;
|
||||
while ((cp = remglob(dummyargv, 0, &emesg)) != NULL) {
|
||||
char *tcp;
|
||||
|
||||
if (!mflag)
|
||||
continue;
|
||||
if (*cp == '\0') {
|
||||
mflag = 0;
|
||||
continue;
|
||||
}
|
||||
tcp = strrchr(cp, '/');
|
||||
if (tcp)
|
||||
tcp++;
|
||||
else
|
||||
tcp = cp;
|
||||
tcp = ftp_strdup(tcp);
|
||||
ftp_sl_add(dirlist, tcp);
|
||||
}
|
||||
if (emesg != NULL) {
|
||||
fprintf(ttyout, "\n%s\n", emesg);
|
||||
return (CC_REDISPLAY);
|
||||
}
|
||||
(void)strlcpy(lastdir, dir, sizeof(lastdir));
|
||||
dirchange = 0;
|
||||
}
|
||||
|
||||
words = ftp_sl_init();
|
||||
for (i = 0; i < dirlist->sl_cur; i++) {
|
||||
cp = dirlist->sl_str[i];
|
||||
if (strlen(file) > strlen(cp))
|
||||
continue;
|
||||
if (strncmp(file, cp, strlen(file)) == 0)
|
||||
ftp_sl_add(words, cp);
|
||||
}
|
||||
rv = complete_ambiguous(file, list, words);
|
||||
sl_free(words, 0);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic complete routine
|
||||
*/
|
||||
unsigned char
|
||||
complete(EditLine *cel, int ch)
|
||||
{
|
||||
static char word[FTPBUFLEN];
|
||||
static size_t lastc_argc, lastc_argo;
|
||||
|
||||
struct cmd *c;
|
||||
const LineInfo *lf;
|
||||
int dolist, cmpltype;
|
||||
size_t celems, len;
|
||||
|
||||
lf = el_line(cel);
|
||||
len = lf->lastchar - lf->buffer;
|
||||
if (len >= sizeof(line))
|
||||
return (CC_ERROR);
|
||||
(void)strlcpy(line, lf->buffer, len + 1);
|
||||
cursor_pos = line + (lf->cursor - lf->buffer);
|
||||
lastc_argc = cursor_argc; /* remember last cursor pos */
|
||||
lastc_argo = cursor_argo;
|
||||
makeargv(); /* build argc/argv of current line */
|
||||
|
||||
if (cursor_argo >= sizeof(word))
|
||||
return (CC_ERROR);
|
||||
|
||||
dolist = 0;
|
||||
/* if cursor and word is same, list alternatives */
|
||||
if (lastc_argc == cursor_argc && lastc_argo == cursor_argo
|
||||
&& strncmp(word, margv[cursor_argc] ? margv[cursor_argc] : "",
|
||||
cursor_argo) == 0)
|
||||
dolist = 1;
|
||||
else if (cursor_argc < (size_t)margc)
|
||||
(void)strlcpy(word, margv[cursor_argc], cursor_argo + 1);
|
||||
word[cursor_argo] = '\0';
|
||||
|
||||
if (cursor_argc == 0)
|
||||
return (complete_command(word, dolist));
|
||||
|
||||
c = getcmd(margv[0]);
|
||||
if (c == (struct cmd *)-1 || c == 0)
|
||||
return (CC_ERROR);
|
||||
celems = strlen(c->c_complete);
|
||||
|
||||
/* check for 'continuation' completes (which are uppercase) */
|
||||
if ((cursor_argc > celems) && (celems > 0)
|
||||
&& isupper((unsigned char) c->c_complete[celems-1]))
|
||||
cursor_argc = celems;
|
||||
|
||||
if (cursor_argc > celems)
|
||||
return (CC_ERROR);
|
||||
|
||||
cmpltype = c->c_complete[cursor_argc - 1];
|
||||
switch (cmpltype) {
|
||||
case 'c': /* command complete */
|
||||
case 'C':
|
||||
return (complete_command(word, dolist));
|
||||
case 'l': /* local complete */
|
||||
case 'L':
|
||||
return (complete_local(word, dolist));
|
||||
case 'n': /* no complete */
|
||||
case 'N': /* no complete */
|
||||
return (CC_ERROR);
|
||||
case 'o': /* local complete */
|
||||
case 'O':
|
||||
return (complete_option(word, dolist));
|
||||
case 'r': /* remote complete */
|
||||
case 'R':
|
||||
if (connected != -1) {
|
||||
fputs("\nMust be logged in to complete.\n",
|
||||
ttyout);
|
||||
return (CC_REDISPLAY);
|
||||
}
|
||||
return (complete_remote(word, dolist));
|
||||
default:
|
||||
errx(1, "complete: unknown complete type `%c'",
|
||||
cmpltype);
|
||||
return (CC_ERROR);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#endif /* !NO_EDITCOMPLETE */
|
145
usr.bin/ftp/domacro.c
Normal file
145
usr.bin/ftp/domacro.c
Normal file
|
@ -0,0 +1,145 @@
|
|||
/* $NetBSD: domacro.c,v 1.22 2009/04/12 10:18:52 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: domacro.c,v 1.22 2009/04/12 10:18:52 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ftp_var.h"
|
||||
|
||||
void
|
||||
domacro(int argc, char *argv[])
|
||||
{
|
||||
int i, j, count = 2, loopflg = 0;
|
||||
char *cp1, *cp2, line2[FTPBUFLEN];
|
||||
struct cmd *c;
|
||||
char cmdbuf[MAX_C_NAME];
|
||||
|
||||
if ((argc == 0 && argv != NULL) ||
|
||||
(argc < 2 && !another(&argc, &argv, "macro name"))) {
|
||||
UPRINTF("usage: %s macro_name [args]\n", argv[0]);
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < macnum; ++i) {
|
||||
if (!strncmp(argv[1], macros[i].mac_name, 9))
|
||||
break;
|
||||
}
|
||||
if (i == macnum) {
|
||||
fprintf(ttyout, "'%s' macro not found.\n", argv[1]);
|
||||
code = -1;
|
||||
return;
|
||||
}
|
||||
(void)strlcpy(line2, line, sizeof(line2));
|
||||
TOP:
|
||||
cp1 = macros[i].mac_start;
|
||||
while (cp1 != macros[i].mac_end) {
|
||||
while (isspace((unsigned char)*cp1))
|
||||
cp1++;
|
||||
cp2 = line;
|
||||
while (*cp1 != '\0') {
|
||||
switch(*cp1) {
|
||||
case '\\':
|
||||
*cp2++ = *++cp1;
|
||||
break;
|
||||
case '$':
|
||||
if (isdigit((unsigned char)*(cp1+1))) {
|
||||
j = 0;
|
||||
while (isdigit((unsigned char)*++cp1))
|
||||
j = 10*j + *cp1 - '0';
|
||||
cp1--;
|
||||
if (argc - 2 >= j) {
|
||||
(void)strlcpy(cp2, argv[j+1],
|
||||
sizeof(line) - (cp2 - line));
|
||||
cp2 += strlen(argv[j+1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (*(cp1+1) == 'i') {
|
||||
loopflg = 1;
|
||||
cp1++;
|
||||
if (count < argc) {
|
||||
(void)strlcpy(cp2, argv[count],
|
||||
sizeof(line) - (cp2 - line));
|
||||
cp2 += strlen(argv[count]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* intentional drop through */
|
||||
default:
|
||||
*cp2++ = *cp1;
|
||||
break;
|
||||
}
|
||||
if (*cp1 != '\0')
|
||||
cp1++;
|
||||
}
|
||||
*cp2 = '\0';
|
||||
makeargv();
|
||||
c = getcmd(margv[0]);
|
||||
if (c == (struct cmd *)-1) {
|
||||
fputs("?Ambiguous command.\n", ttyout);
|
||||
code = -1;
|
||||
} else if (c == 0) {
|
||||
fputs("?Invalid command.\n", ttyout);
|
||||
code = -1;
|
||||
} else if (c->c_conn && !connected) {
|
||||
fputs("Not connected.\n", ttyout);
|
||||
code = -1;
|
||||
} else {
|
||||
if (verbose) {
|
||||
fputs(line, ttyout);
|
||||
putc('\n', ttyout);
|
||||
}
|
||||
(void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf));
|
||||
margv[0] = cmdbuf;
|
||||
(*c->c_handler)(margc, margv);
|
||||
if (bell && c->c_bell)
|
||||
(void)putc('\007', ttyout);
|
||||
(void)strlcpy(line, line2, sizeof(line));
|
||||
makeargv();
|
||||
argc = margc;
|
||||
argv = margv;
|
||||
}
|
||||
if (cp1 != macros[i].mac_end)
|
||||
cp1++;
|
||||
}
|
||||
if (loopflg && ++count < argc)
|
||||
goto TOP;
|
||||
}
|
248
usr.bin/ftp/extern.h
Normal file
248
usr.bin/ftp/extern.h
Normal file
|
@ -0,0 +1,248 @@
|
|||
/* $NetBSD: extern.h,v 1.80 2012/07/04 06:09:37 is Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1994 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)extern.h 8.3 (Berkeley) 10/9/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
struct sockaddr;
|
||||
struct tm;
|
||||
struct addrinfo;
|
||||
|
||||
void abort_remote(FILE *);
|
||||
void account(int, char **);
|
||||
void ai_unmapped(struct addrinfo *);
|
||||
int another(int *, char ***, const char *);
|
||||
int auto_fetch(int, char **);
|
||||
int auto_put(int, char **, const char *);
|
||||
void blkfree(char **);
|
||||
void cd(int, char **);
|
||||
void cdup(int, char **);
|
||||
void changetype(int, int);
|
||||
void cleanuppeer(void);
|
||||
void cmdabort(int);
|
||||
void cmdtimeout(int);
|
||||
void cmdscanner(void);
|
||||
int command(const char *, ...)
|
||||
__attribute__((__format__(__printf__, 1, 2)));
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
unsigned char complete(EditLine *, int);
|
||||
void controlediting(void);
|
||||
#endif /* !NO_EDITCOMPLETE */
|
||||
void crankrate(int);
|
||||
FILE *dataconn(const char *);
|
||||
void delete(int, char **);
|
||||
void disconnect(int, char **);
|
||||
void do_chmod(int, char **);
|
||||
void do_umask(int, char **);
|
||||
void domacro(int, char **);
|
||||
void doproxy(int, char **);
|
||||
void feat(int, char **);
|
||||
void fget(int, char **);
|
||||
int fileindir(const char *, const char *);
|
||||
int foregroundproc(void);
|
||||
void formatbuf(char *, size_t, const char *);
|
||||
void ftpvis(char *, size_t, const char *, size_t);
|
||||
int ftp_login(const char *, const char *, const char *);
|
||||
void get(int, char **);
|
||||
struct cmd *getcmd(const char *);
|
||||
int getit(int, char **, int, const char *);
|
||||
int get_line(FILE *, char *, size_t, const char **);
|
||||
struct option *getoption(const char *);
|
||||
char *getoptionvalue(const char *);
|
||||
void getremoteinfo(void);
|
||||
int getreply(int);
|
||||
char *globulize(const char *);
|
||||
char *gunique(const char *);
|
||||
void help(int, char **);
|
||||
char *hookup(const char *, const char *);
|
||||
void idlecmd(int, char **);
|
||||
int initconn(void);
|
||||
__dead void intr(int);
|
||||
int isipv6addr(const char *);
|
||||
void list_vertical(StringList *);
|
||||
void lcd(int, char **);
|
||||
void lostpeer(int);
|
||||
void lpage(int, char **);
|
||||
void lpwd(int, char **);
|
||||
void ls(int, char **);
|
||||
void macdef(int, char **);
|
||||
void makeargv(void);
|
||||
void makedir(int, char **);
|
||||
void mdelete(int, char **);
|
||||
void mget(int, char **);
|
||||
void mls(int, char **);
|
||||
void mlst(int, char **);
|
||||
void modtime(int, char **);
|
||||
void mput(int, char **);
|
||||
const char *onoff(int);
|
||||
void opts(int, char **);
|
||||
void newer(int, char **);
|
||||
void page(int, char **);
|
||||
const char *parse_rfc2616time(struct tm *, const char *);
|
||||
int parserate(int, char **, int);
|
||||
char *prompt(void);
|
||||
__dead void proxabort(int);
|
||||
void proxtrans(const char *, const char *, const char *);
|
||||
void psabort(int);
|
||||
void pswitch(int);
|
||||
void put(int, char **);
|
||||
void pwd(int, char **);
|
||||
void quit(int, char **);
|
||||
void quote(int, char **);
|
||||
void quote1(const char *, int, char **);
|
||||
void recvrequest(const char *, const char *, const char *,
|
||||
const char *, int, int);
|
||||
void reget(int, char **);
|
||||
char *remglob(char **, int, const char **);
|
||||
time_t remotemodtime(const char *, int);
|
||||
off_t remotesize(const char *, int);
|
||||
void removedir(int, char **);
|
||||
void renamefile(int, char **);
|
||||
void reset(int, char **);
|
||||
void restart(int, char **);
|
||||
const char *rfc2822time(const struct tm *);
|
||||
void rmthelp(int, char **);
|
||||
void rmtstatus(int, char **);
|
||||
char *rprompt(void);
|
||||
int ruserpass(const char *, char **, char **, char **);
|
||||
void sendrequest(const char *, const char *, const char *, int);
|
||||
void setascii(int, char **);
|
||||
void setbell(int, char **);
|
||||
void setbinary(int, char **);
|
||||
void setcase(int, char **);
|
||||
void setcr(int, char **);
|
||||
void setdebug(int, char **);
|
||||
void setedit(int, char **);
|
||||
void setepsv4(int, char **);
|
||||
void setepsv6(int, char **);
|
||||
void setepsv(int, char **);
|
||||
void setform(int, char **);
|
||||
void setftmode(int, char **);
|
||||
void setgate(int, char **);
|
||||
void setglob(int, char **);
|
||||
void sethash(int, char **);
|
||||
void setnmap(int, char **);
|
||||
void setntrans(int, char **);
|
||||
void setoption(int, char **);
|
||||
void setpassive(int, char **);
|
||||
void setpeer(int, char **);
|
||||
void setport(int, char **);
|
||||
void setpreserve(int, char **);
|
||||
void setprogress(int, char **);
|
||||
void setprompt(int, char **);
|
||||
void setrate(int, char **);
|
||||
void setrunique(int, char **);
|
||||
void setstruct(int, char **);
|
||||
void setsunique(int, char **);
|
||||
void settenex(int, char **);
|
||||
void settrace(int, char **);
|
||||
void setttywidth(int);
|
||||
void settype(int, char **);
|
||||
void setupsockbufsize(int);
|
||||
void setverbose(int, char **);
|
||||
void setxferbuf(int, char **);
|
||||
void set_option(const char *, const char *, int);
|
||||
void shell(int, char **);
|
||||
void site(int, char **);
|
||||
void sizecmd(int, char **);
|
||||
char *slurpstring(void);
|
||||
void status(int, char **);
|
||||
int strsuftoi(const char *);
|
||||
void syst(int, char **);
|
||||
int togglevar(int, char **, int *, const char *);
|
||||
void unsetoption(int, char **);
|
||||
void updatelocalcwd(void);
|
||||
void updateremotecwd(void);
|
||||
void user(int, char **);
|
||||
int ftp_connect(int, const struct sockaddr *, socklen_t, int);
|
||||
int ftp_listen(int, int);
|
||||
int ftp_poll(struct pollfd *, int, int);
|
||||
void *ftp_malloc(size_t);
|
||||
StringList *ftp_sl_init(void);
|
||||
void ftp_sl_add(StringList *, char *);
|
||||
char *ftp_strdup(const char *);
|
1979
usr.bin/ftp/fetch.c
Normal file
1979
usr.bin/ftp/fetch.c
Normal file
File diff suppressed because it is too large
Load diff
2421
usr.bin/ftp/ftp.1
Normal file
2421
usr.bin/ftp/ftp.1
Normal file
File diff suppressed because it is too large
Load diff
2178
usr.bin/ftp/ftp.c
Normal file
2178
usr.bin/ftp/ftp.c
Normal file
File diff suppressed because it is too large
Load diff
354
usr.bin/ftp/ftp_var.h
Normal file
354
usr.bin/ftp/ftp_var.h
Normal file
|
@ -0,0 +1,354 @@
|
|||
/* $NetBSD: ftp_var.h,v 1.82 2012/12/21 18:07:36 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)ftp_var.h 8.4 (Berkeley) 10/9/94
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 1997 and 1998 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FTP global variables.
|
||||
*/
|
||||
|
||||
#ifdef SMALL
|
||||
#undef NO_EDITCOMPLETE
|
||||
#define NO_EDITCOMPLETE
|
||||
#undef NO_PROGRESS
|
||||
#define NO_PROGRESS
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stringlist.h>
|
||||
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
#include <histedit.h>
|
||||
#endif /* !NO_EDITCOMPLETE */
|
||||
|
||||
#include "extern.h"
|
||||
#include "progressbar.h"
|
||||
|
||||
/*
|
||||
* Format of command table.
|
||||
*/
|
||||
struct cmd {
|
||||
const char *c_name; /* name of command */
|
||||
const char *c_help; /* help string */
|
||||
char c_bell; /* give bell when command completes */
|
||||
char c_conn; /* must be connected to use command */
|
||||
char c_proxy; /* proxy server may execute */
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
const char *c_complete; /* context sensitive completion list */
|
||||
#endif /* !NO_EDITCOMPLETE */
|
||||
void (*c_handler)(int, char **); /* function to call */
|
||||
};
|
||||
|
||||
#define MAX_C_NAME 12 /* maximum length of cmd.c_name */
|
||||
|
||||
/*
|
||||
* Format of macro table
|
||||
*/
|
||||
struct macel {
|
||||
char mac_name[9]; /* macro name */
|
||||
char *mac_start; /* start of macro in macbuf */
|
||||
char *mac_end; /* end of macro in macbuf */
|
||||
};
|
||||
|
||||
/*
|
||||
* Format of option table
|
||||
*/
|
||||
struct option {
|
||||
const char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
/*
|
||||
* Indices to features[]; an array containing status of remote server
|
||||
* features; -1 not known (FEAT failed), 0 absent, 1 present.
|
||||
*/
|
||||
enum {
|
||||
FEAT_FEAT = 0, /* FEAT, OPTS */
|
||||
FEAT_MDTM, /* MDTM */
|
||||
FEAT_MLST, /* MLSD, MLST */
|
||||
FEAT_REST_STREAM, /* RESTart STREAM */
|
||||
FEAT_SIZE, /* SIZE */
|
||||
FEAT_TVFS, /* TVFS (not used) */
|
||||
FEAT_max
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Global defines
|
||||
*/
|
||||
#define FTPBUFLEN MAXPATHLEN + 200
|
||||
#define MAX_IN_PORT_T 0xffffU
|
||||
|
||||
#define HASHBYTES 1024 /* default mark for `hash' command */
|
||||
#define DEFAULTINCR 1024 /* default increment for `rate' command */
|
||||
|
||||
#define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */
|
||||
#define HTTP_PORT 80 /* default if ! getservbyname("http/tcp") */
|
||||
#define HTTPS_PORT 443 /* default if ! getservbyname("https/tcp") */
|
||||
#ifndef GATE_PORT
|
||||
#define GATE_PORT 21 /* default if ! getservbyname("ftpgate/tcp") */
|
||||
#endif
|
||||
#ifndef GATE_SERVER
|
||||
#define GATE_SERVER "" /* default server */
|
||||
#endif
|
||||
|
||||
#define DEFAULTPAGER "more" /* default pager if $PAGER isn't set */
|
||||
#define DEFAULTPROMPT "ftp> " /* default prompt if `set prompt' is empty */
|
||||
#define DEFAULTRPROMPT "" /* default rprompt if `set rprompt' is empty */
|
||||
|
||||
#define TMPFILE "ftpXXXXXXXXXX"
|
||||
|
||||
|
||||
#ifndef GLOBAL
|
||||
#define GLOBAL extern
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Options and other state info.
|
||||
*/
|
||||
GLOBAL int trace; /* trace packets exchanged */
|
||||
GLOBAL int hash; /* print # for each buffer transferred */
|
||||
GLOBAL int mark; /* number of bytes between hashes */
|
||||
GLOBAL int sendport; /* use PORT/LPRT cmd for each data connection */
|
||||
GLOBAL int connected; /* 1 = connected to server, -1 = logged in */
|
||||
GLOBAL int interactive; /* interactively prompt on m* cmds */
|
||||
GLOBAL int confirmrest; /* confirm rest of current m* cmd */
|
||||
GLOBAL int ftp_debug; /* debugging level */
|
||||
GLOBAL int bell; /* ring bell on cmd completion */
|
||||
GLOBAL int doglob; /* glob local file names */
|
||||
GLOBAL int autologin; /* establish user account on connection */
|
||||
GLOBAL int proxy; /* proxy server connection active */
|
||||
GLOBAL int proxflag; /* proxy connection exists */
|
||||
GLOBAL int gatemode; /* use gate-ftp */
|
||||
GLOBAL const char *gateserver; /* server to use for gate-ftp */
|
||||
GLOBAL int sunique; /* store files on server with unique name */
|
||||
GLOBAL int runique; /* store local files with unique name */
|
||||
GLOBAL int mcase; /* map upper to lower case for mget names */
|
||||
GLOBAL int ntflag; /* use ntin ntout tables for name translation */
|
||||
GLOBAL int mapflag; /* use mapin mapout templates on file names */
|
||||
GLOBAL int preserve; /* preserve modification time on files */
|
||||
GLOBAL int code; /* return/reply code for ftp command */
|
||||
GLOBAL int crflag; /* if 1, strip car. rets. on ascii gets */
|
||||
GLOBAL int passivemode; /* passive mode enabled */
|
||||
GLOBAL int activefallback; /* fall back to active mode if passive fails */
|
||||
GLOBAL char *altarg; /* argv[1] with no shell-like preprocessing */
|
||||
GLOBAL char ntin[17]; /* input translation table */
|
||||
GLOBAL char ntout[17]; /* output translation table */
|
||||
GLOBAL char mapin[MAXPATHLEN]; /* input map template */
|
||||
GLOBAL char mapout[MAXPATHLEN]; /* output map template */
|
||||
GLOBAL char typename[32]; /* name of file transfer type */
|
||||
GLOBAL int type; /* requested file transfer type */
|
||||
GLOBAL int curtype; /* current file transfer type */
|
||||
GLOBAL char structname[32]; /* name of file transfer structure */
|
||||
GLOBAL int stru; /* file transfer structure */
|
||||
GLOBAL char formname[32]; /* name of file transfer format */
|
||||
GLOBAL int form; /* file transfer format */
|
||||
GLOBAL char modename[32]; /* name of file transfer mode */
|
||||
GLOBAL int mode; /* file transfer mode */
|
||||
GLOBAL char bytename[32]; /* local byte size in ascii */
|
||||
GLOBAL int bytesize; /* local byte size in binary */
|
||||
GLOBAL int anonftp; /* automatic anonymous login */
|
||||
GLOBAL int dirchange; /* remote directory changed by cd command */
|
||||
GLOBAL int flushcache; /* set HTTP cache flush headers with request */
|
||||
GLOBAL int rate_get; /* maximum get xfer rate */
|
||||
GLOBAL int rate_get_incr; /* increment for get xfer rate */
|
||||
GLOBAL int rate_put; /* maximum put xfer rate */
|
||||
GLOBAL int rate_put_incr; /* increment for put xfer rate */
|
||||
GLOBAL int retry_connect; /* seconds between retrying connection */
|
||||
GLOBAL const char *tmpdir; /* temporary directory */
|
||||
GLOBAL int epsv4; /* use EPSV/EPRT on IPv4 connections */
|
||||
GLOBAL int epsv4bad; /* EPSV doesn't work on the current server */
|
||||
GLOBAL int epsv6; /* use EPSV/EPRT on IPv6 connections */
|
||||
GLOBAL int epsv6bad; /* EPSV doesn't work on the current server */
|
||||
GLOBAL int editing; /* command line editing enabled */
|
||||
GLOBAL int features[FEAT_max]; /* remote FEATures supported */
|
||||
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
GLOBAL EditLine *el; /* editline(3) status structure */
|
||||
GLOBAL History *hist; /* editline(3) history structure */
|
||||
GLOBAL char *cursor_pos; /* cursor position we're looking for */
|
||||
GLOBAL size_t cursor_argc; /* location of cursor in margv */
|
||||
GLOBAL size_t cursor_argo; /* offset of cursor in margv[cursor_argc] */
|
||||
#endif /* !NO_EDITCOMPLETE */
|
||||
|
||||
GLOBAL char *hostname; /* name of host connected to */
|
||||
GLOBAL int unix_server; /* server is unix, can use binary for ascii */
|
||||
GLOBAL int unix_proxy; /* proxy is unix, can use binary for ascii */
|
||||
GLOBAL char localcwd[MAXPATHLEN]; /* local dir */
|
||||
GLOBAL char remotecwd[MAXPATHLEN]; /* remote dir */
|
||||
GLOBAL char *username; /* name of user logged in as. (dynamic) */
|
||||
|
||||
GLOBAL sa_family_t family; /* address family to use for connections */
|
||||
GLOBAL const char *ftpport; /* port number to use for FTP connections */
|
||||
GLOBAL const char *httpport; /* port number to use for HTTP connections */
|
||||
#ifdef WITH_SSL
|
||||
GLOBAL const char *httpsport; /* port number to use for HTTPS connections */
|
||||
#endif
|
||||
GLOBAL const char *gateport; /* port number to use for gateftp connections */
|
||||
GLOBAL struct addrinfo *bindai; /* local address to bind as */
|
||||
|
||||
GLOBAL char *outfile; /* filename to output URLs to */
|
||||
GLOBAL int restartautofetch; /* restart auto-fetch */
|
||||
|
||||
GLOBAL char line[FTPBUFLEN]; /* input line buffer */
|
||||
GLOBAL char *stringbase; /* current scan point in line buffer */
|
||||
GLOBAL char argbuf[FTPBUFLEN]; /* argument storage buffer */
|
||||
GLOBAL char *argbase; /* current storage point in arg buffer */
|
||||
GLOBAL StringList *marg_sl; /* stringlist containing margv */
|
||||
GLOBAL int margc; /* count of arguments on input line */
|
||||
#define margv (marg_sl->sl_str) /* args parsed from input line */
|
||||
GLOBAL int cpend; /* flag: if != 0, then pending server reply */
|
||||
GLOBAL int mflag; /* flag: if != 0, then active multi command */
|
||||
|
||||
GLOBAL int options; /* used during socket creation */
|
||||
|
||||
GLOBAL int sndbuf_size; /* socket send buffer size */
|
||||
GLOBAL int rcvbuf_size; /* socket receive buffer size */
|
||||
|
||||
GLOBAL int macnum; /* number of defined macros */
|
||||
GLOBAL struct macel macros[16];
|
||||
GLOBAL char macbuf[4096];
|
||||
|
||||
GLOBAL char *localhome; /* local home directory */
|
||||
GLOBAL char *localname; /* local user name */
|
||||
GLOBAL char netrc[MAXPATHLEN]; /* path to .netrc file */
|
||||
GLOBAL char reply_string[BUFSIZ]; /* first line of previous reply */
|
||||
GLOBAL void (*reply_callback)(const char *);
|
||||
/*
|
||||
* function to call for each line in
|
||||
* the server's reply except for the
|
||||
* first (`xxx-') and last (`xxx ')
|
||||
*/
|
||||
|
||||
GLOBAL volatile sig_atomic_t sigint_raised;
|
||||
|
||||
GLOBAL FILE *cin;
|
||||
GLOBAL FILE *cout;
|
||||
GLOBAL int data;
|
||||
|
||||
extern struct cmd cmdtab[];
|
||||
extern struct option optiontab[];
|
||||
|
||||
|
||||
#define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0'))
|
||||
#define FREEPTR(x) if ((x) != NULL) { free(x); (x) = NULL; }
|
||||
|
||||
#ifdef BSD4_4
|
||||
# define HAVE_STRUCT_SOCKADDR_IN_SIN_LEN 1
|
||||
#endif
|
||||
|
||||
#ifdef NO_LONG_LONG
|
||||
# define STRTOLL(x,y,z) strtol(x,y,z)
|
||||
#else
|
||||
# define STRTOLL(x,y,z) strtoll(x,y,z)
|
||||
#endif
|
||||
|
||||
#ifdef NO_DEBUG
|
||||
#define DPRINTF(...)
|
||||
#define DWARN(...)
|
||||
#else
|
||||
#define DPRINTF(...) if (ftp_debug) (void)fprintf(ttyout, __VA_ARGS__)
|
||||
#define DWARN(...) if (ftp_debug) warn(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define STRorNULL(s) ((s) ? (s) : "<null>")
|
||||
|
||||
#ifdef NO_USAGE
|
||||
void xusage(void);
|
||||
#define UPRINTF(...) xusage()
|
||||
#else
|
||||
#define UPRINTF(...) (void)fprintf(ttyout, __VA_ARGS__)
|
||||
#endif
|
1057
usr.bin/ftp/main.c
Normal file
1057
usr.bin/ftp/main.c
Normal file
File diff suppressed because it is too large
Load diff
472
usr.bin/ftp/progressbar.c
Normal file
472
usr.bin/ftp/progressbar.c
Normal file
|
@ -0,0 +1,472 @@
|
|||
/* $NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: progressbar.c,v 1.22 2012/06/27 22:07:36 riastradh Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* FTP User Program -- Misc support routines
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <tzfile.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "progressbar.h"
|
||||
|
||||
#if !defined(NO_PROGRESS)
|
||||
/*
|
||||
* return non-zero if we're the current foreground process
|
||||
*/
|
||||
int
|
||||
foregroundproc(void)
|
||||
{
|
||||
static pid_t pgrp = -1;
|
||||
|
||||
if (pgrp == -1)
|
||||
pgrp = getpgrp();
|
||||
|
||||
return (tcgetpgrp(fileno(ttyout)) == pgrp);
|
||||
}
|
||||
#endif /* !defined(NO_PROGRESS) */
|
||||
|
||||
|
||||
static void updateprogressmeter(int);
|
||||
|
||||
/*
|
||||
* SIGALRM handler to update the progress meter
|
||||
*/
|
||||
static void
|
||||
updateprogressmeter(int dummy)
|
||||
{
|
||||
int oerrno = errno;
|
||||
|
||||
progressmeter(0);
|
||||
errno = oerrno;
|
||||
}
|
||||
|
||||
/*
|
||||
* List of order of magnitude suffixes, per IEC 60027-2.
|
||||
*/
|
||||
static const char * const suffixes[] = {
|
||||
"", /* 2^0 (byte) */
|
||||
"KiB", /* 2^10 Kibibyte */
|
||||
"MiB", /* 2^20 Mebibyte */
|
||||
"GiB", /* 2^30 Gibibyte */
|
||||
"TiB", /* 2^40 Tebibyte */
|
||||
"PiB", /* 2^50 Pebibyte */
|
||||
"EiB", /* 2^60 Exbibyte */
|
||||
#if 0
|
||||
/* The following are not necessary for signed 64-bit off_t */
|
||||
"ZiB", /* 2^70 Zebibyte */
|
||||
"YiB", /* 2^80 Yobibyte */
|
||||
#endif
|
||||
};
|
||||
#define NSUFFIXES (int)(sizeof(suffixes) / sizeof(suffixes[0]))
|
||||
|
||||
/*
|
||||
* Display a transfer progress bar if progress is non-zero.
|
||||
* SIGALRM is hijacked for use by this function.
|
||||
* - Before the transfer, set filesize to size of file (or -1 if unknown),
|
||||
* and call with flag = -1. This starts the once per second timer,
|
||||
* and a call to updateprogressmeter() upon SIGALRM.
|
||||
* - During the transfer, updateprogressmeter will call progressmeter
|
||||
* with flag = 0
|
||||
* - After the transfer, call with flag = 1
|
||||
*/
|
||||
static struct timeval start;
|
||||
static struct timeval lastupdate;
|
||||
|
||||
#define BUFLEFT (sizeof(buf) - len)
|
||||
|
||||
void
|
||||
progressmeter(int flag)
|
||||
{
|
||||
static off_t lastsize;
|
||||
off_t cursize;
|
||||
struct timeval now, wait;
|
||||
#ifndef NO_PROGRESS
|
||||
struct timeval td;
|
||||
off_t abbrevsize, bytespersec;
|
||||
double elapsed;
|
||||
int ratio, i, remaining, barlength;
|
||||
|
||||
/*
|
||||
* Work variables for progress bar.
|
||||
*
|
||||
* XXX: if the format of the progress bar changes
|
||||
* (especially the number of characters in the
|
||||
* `static' portion of it), be sure to update
|
||||
* these appropriately.
|
||||
*/
|
||||
#endif
|
||||
size_t len;
|
||||
char buf[256]; /* workspace for progress bar */
|
||||
#ifndef NO_PROGRESS
|
||||
#define BAROVERHEAD 45 /* non `*' portion of progress bar */
|
||||
/*
|
||||
* stars should contain at least
|
||||
* sizeof(buf) - BAROVERHEAD entries
|
||||
*/
|
||||
static const char stars[] =
|
||||
"*****************************************************************************"
|
||||
"*****************************************************************************"
|
||||
"*****************************************************************************";
|
||||
|
||||
#endif
|
||||
|
||||
if (flag == -1) {
|
||||
(void)gettimeofday(&start, NULL);
|
||||
lastupdate = start;
|
||||
lastsize = restart_point;
|
||||
}
|
||||
|
||||
(void)gettimeofday(&now, NULL);
|
||||
cursize = bytes + restart_point;
|
||||
timersub(&now, &lastupdate, &wait);
|
||||
if (cursize > lastsize) {
|
||||
lastupdate = now;
|
||||
lastsize = cursize;
|
||||
wait.tv_sec = 0;
|
||||
} else {
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
if (quit_time > 0 && wait.tv_sec > quit_time) {
|
||||
len = snprintf(buf, sizeof(buf), "\r\n%s: "
|
||||
"transfer aborted because stalled for %lu sec.\r\n",
|
||||
getprogname(), (unsigned long)wait.tv_sec);
|
||||
(void)write(fileno(ttyout), buf, len);
|
||||
alarmtimer(0);
|
||||
(void)xsignal(SIGALRM, SIG_DFL);
|
||||
siglongjmp(toplevel, 1);
|
||||
}
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
}
|
||||
/*
|
||||
* Always set the handler even if we are not the foreground process.
|
||||
*/
|
||||
#ifdef STANDALONE_PROGRESS
|
||||
if (progress) {
|
||||
#else
|
||||
if (quit_time > 0 || progress) {
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
if (flag == -1) {
|
||||
(void)xsignal_restart(SIGALRM, updateprogressmeter, 1);
|
||||
alarmtimer(1); /* set alarm timer for 1 Hz */
|
||||
} else if (flag == 1) {
|
||||
alarmtimer(0);
|
||||
(void)xsignal(SIGALRM, SIG_DFL);
|
||||
}
|
||||
}
|
||||
#ifndef NO_PROGRESS
|
||||
if (!progress)
|
||||
return;
|
||||
len = 0;
|
||||
|
||||
/*
|
||||
* print progress bar only if we are foreground process.
|
||||
*/
|
||||
if (! foregroundproc())
|
||||
return;
|
||||
|
||||
len += snprintf(buf + len, BUFLEFT, "\r");
|
||||
if (prefix)
|
||||
len += snprintf(buf + len, BUFLEFT, "%s", prefix);
|
||||
if (filesize > 0) {
|
||||
ratio = (int)((double)cursize * 100.0 / (double)filesize);
|
||||
ratio = MAX(ratio, 0);
|
||||
ratio = MIN(ratio, 100);
|
||||
len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio);
|
||||
|
||||
/*
|
||||
* calculate the length of the `*' bar, ensuring that
|
||||
* the number of stars won't exceed the buffer size
|
||||
*/
|
||||
barlength = MIN((int)(sizeof(buf) - 1), ttywidth) - BAROVERHEAD;
|
||||
if (prefix)
|
||||
barlength -= (int)strlen(prefix);
|
||||
if (barlength > 0) {
|
||||
i = barlength * ratio / 100;
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
"|%.*s%*s|", i, stars, (int)(barlength - i), "");
|
||||
}
|
||||
}
|
||||
|
||||
abbrevsize = cursize;
|
||||
for (i = 0; abbrevsize >= 100000 && i < NSUFFIXES; i++)
|
||||
abbrevsize >>= 10;
|
||||
if (i == NSUFFIXES)
|
||||
i--;
|
||||
len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %-3s ",
|
||||
(LLT)abbrevsize,
|
||||
suffixes[i]);
|
||||
|
||||
timersub(&now, &start, &td);
|
||||
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
|
||||
|
||||
bytespersec = 0;
|
||||
if (bytes > 0) {
|
||||
bytespersec = bytes;
|
||||
if (elapsed > 0.0)
|
||||
bytespersec /= elapsed;
|
||||
}
|
||||
for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++)
|
||||
bytespersec >>= 10;
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
" " LLFP("3") ".%02d %.2sB/s ",
|
||||
(LLT)(bytespersec / 1024),
|
||||
(int)((bytespersec % 1024) * 100 / 1024),
|
||||
suffixes[i]);
|
||||
|
||||
if (filesize > 0) {
|
||||
if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) {
|
||||
len += snprintf(buf + len, BUFLEFT, " --:-- ETA");
|
||||
} else if (wait.tv_sec >= STALLTIME) {
|
||||
len += snprintf(buf + len, BUFLEFT, " - stalled -");
|
||||
} else {
|
||||
remaining = (int)
|
||||
((filesize - restart_point) / (bytes / elapsed) -
|
||||
elapsed);
|
||||
if (remaining >= 100 * SECSPERHOUR)
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
" --:-- ETA");
|
||||
else {
|
||||
i = remaining / SECSPERHOUR;
|
||||
if (i)
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
"%2d:", i);
|
||||
else
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
" ");
|
||||
i = remaining % SECSPERHOUR;
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
"%02d:%02d ETA", i / 60, i % 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag == 1)
|
||||
len += snprintf(buf + len, BUFLEFT, "\n");
|
||||
(void)write(fileno(ttyout), buf, len);
|
||||
|
||||
#endif /* !NO_PROGRESS */
|
||||
}
|
||||
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
/*
|
||||
* Display transfer statistics.
|
||||
* Requires start to be initialised by progressmeter(-1),
|
||||
* direction to be defined by xfer routines, and filesize and bytes
|
||||
* to be updated by xfer routines
|
||||
* If siginfo is nonzero, an ETA is displayed, and the output goes to stderr
|
||||
* instead of ttyout.
|
||||
*/
|
||||
void
|
||||
ptransfer(int siginfo)
|
||||
{
|
||||
struct timeval now, td, wait;
|
||||
double elapsed;
|
||||
off_t bytespersec;
|
||||
int remaining, hh, i;
|
||||
size_t len;
|
||||
|
||||
char buf[256]; /* Work variable for transfer status. */
|
||||
|
||||
if (!verbose && !progress && !siginfo)
|
||||
return;
|
||||
|
||||
(void)gettimeofday(&now, NULL);
|
||||
timersub(&now, &start, &td);
|
||||
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
|
||||
bytespersec = 0;
|
||||
if (bytes > 0) {
|
||||
bytespersec = bytes;
|
||||
if (elapsed > 0.0)
|
||||
bytespersec /= elapsed;
|
||||
}
|
||||
len = 0;
|
||||
len += snprintf(buf + len, BUFLEFT, LLF " byte%s %s in ",
|
||||
(LLT)bytes, bytes == 1 ? "" : "s", direction);
|
||||
remaining = (int)elapsed;
|
||||
if (remaining > SECSPERDAY) {
|
||||
int days;
|
||||
|
||||
days = remaining / SECSPERDAY;
|
||||
remaining %= SECSPERDAY;
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
"%d day%s ", days, days == 1 ? "" : "s");
|
||||
}
|
||||
hh = remaining / SECSPERHOUR;
|
||||
remaining %= SECSPERHOUR;
|
||||
if (hh)
|
||||
len += snprintf(buf + len, BUFLEFT, "%2d:", hh);
|
||||
len += snprintf(buf + len, BUFLEFT,
|
||||
"%02d:%02d ", remaining / 60, remaining % 60);
|
||||
|
||||
for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++)
|
||||
bytespersec >>= 10;
|
||||
if (i == NSUFFIXES)
|
||||
i--;
|
||||
len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %.2sB/s)",
|
||||
(LLT)(bytespersec / 1024),
|
||||
(int)((bytespersec % 1024) * 100 / 1024),
|
||||
suffixes[i]);
|
||||
|
||||
if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0
|
||||
&& bytes + restart_point <= filesize) {
|
||||
remaining = (int)((filesize - restart_point) /
|
||||
(bytes / elapsed) - elapsed);
|
||||
hh = remaining / SECSPERHOUR;
|
||||
remaining %= SECSPERHOUR;
|
||||
len += snprintf(buf + len, BUFLEFT, " ETA: ");
|
||||
if (hh)
|
||||
len += snprintf(buf + len, BUFLEFT, "%2d:", hh);
|
||||
len += snprintf(buf + len, BUFLEFT, "%02d:%02d",
|
||||
remaining / 60, remaining % 60);
|
||||
timersub(&now, &lastupdate, &wait);
|
||||
if (wait.tv_sec >= STALLTIME)
|
||||
len += snprintf(buf + len, BUFLEFT, " (stalled)");
|
||||
}
|
||||
len += snprintf(buf + len, BUFLEFT, "\n");
|
||||
(void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* SIG{INFO,QUIT} handler to print transfer stats if a transfer is in progress
|
||||
*/
|
||||
void
|
||||
psummary(int notused)
|
||||
{
|
||||
int oerrno = errno;
|
||||
|
||||
if (bytes > 0) {
|
||||
if (fromatty)
|
||||
write(fileno(ttyout), "\n", 1);
|
||||
ptransfer(1);
|
||||
}
|
||||
errno = oerrno;
|
||||
}
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
|
||||
|
||||
/*
|
||||
* Set the SIGALRM interval timer for wait seconds, 0 to disable.
|
||||
*/
|
||||
void
|
||||
alarmtimer(int wait)
|
||||
{
|
||||
struct itimerval itv;
|
||||
|
||||
itv.it_value.tv_sec = wait;
|
||||
itv.it_value.tv_usec = 0;
|
||||
itv.it_interval = itv.it_value;
|
||||
setitimer(ITIMER_REAL, &itv, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install a POSIX signal handler, allowing the invoker to set whether
|
||||
* the signal should be restartable or not
|
||||
*/
|
||||
sigfunc
|
||||
xsignal_restart(int sig, sigfunc func, int restartable)
|
||||
{
|
||||
struct sigaction act, oact;
|
||||
act.sa_handler = func;
|
||||
|
||||
sigemptyset(&act.sa_mask);
|
||||
#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */
|
||||
act.sa_flags = restartable ? SA_RESTART : 0;
|
||||
#elif defined(SA_INTERRUPT) /* SunOS 4.x */
|
||||
act.sa_flags = restartable ? 0 : SA_INTERRUPT;
|
||||
#else
|
||||
#error "system must have SA_RESTART or SA_INTERRUPT"
|
||||
#endif
|
||||
if (sigaction(sig, &act, &oact) < 0)
|
||||
return (SIG_ERR);
|
||||
return (oact.sa_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install a signal handler with the `restartable' flag set dependent upon
|
||||
* which signal is being set. (This is a wrapper to xsignal_restart())
|
||||
*/
|
||||
sigfunc
|
||||
xsignal(int sig, sigfunc func)
|
||||
{
|
||||
int restartable;
|
||||
|
||||
/*
|
||||
* Some signals print output or change the state of the process.
|
||||
* There should be restartable, so that reads and writes are
|
||||
* not affected. Some signals should cause program flow to change;
|
||||
* these signals should not be restartable, so that the system call
|
||||
* will return with EINTR, and the program will go do something
|
||||
* different. If the signal handler calls longjmp() or siglongjmp(),
|
||||
* it doesn't matter if it's restartable.
|
||||
*/
|
||||
|
||||
switch(sig) {
|
||||
#ifdef SIGINFO
|
||||
case SIGINFO:
|
||||
#endif
|
||||
case SIGQUIT:
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
case SIGWINCH:
|
||||
restartable = 1;
|
||||
break;
|
||||
|
||||
case SIGALRM:
|
||||
case SIGINT:
|
||||
case SIGPIPE:
|
||||
restartable = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* This is unpleasant, but I don't know what would be better.
|
||||
* Right now, this "can't happen"
|
||||
*/
|
||||
errx(1, "xsignal_restart: called with signal %d", sig);
|
||||
}
|
||||
|
||||
return(xsignal_restart(sig, func, restartable));
|
||||
}
|
92
usr.bin/ftp/progressbar.h
Normal file
92
usr.bin/ftp/progressbar.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* $NetBSD: progressbar.h,v 1.8 2009/04/12 10:18:52 lukem Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
#include <setjmp.h>
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
|
||||
#ifndef GLOBAL
|
||||
#define GLOBAL extern
|
||||
#endif
|
||||
|
||||
|
||||
#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */
|
||||
|
||||
typedef void (*sigfunc)(int);
|
||||
|
||||
|
||||
GLOBAL FILE *ttyout; /* stdout, or stderr if retrieving to stdout */
|
||||
|
||||
GLOBAL int progress; /* display transfer progress bar */
|
||||
GLOBAL int ttywidth; /* width of tty */
|
||||
|
||||
GLOBAL off_t bytes; /* current # of bytes read */
|
||||
GLOBAL off_t filesize; /* size of file being transferred */
|
||||
GLOBAL off_t restart_point; /* offset to restart transfer */
|
||||
GLOBAL char *prefix; /* Text written left of progress bar */
|
||||
|
||||
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
GLOBAL int fromatty; /* input is from a terminal */
|
||||
GLOBAL int verbose; /* print messages coming back from server */
|
||||
GLOBAL int quit_time; /* maximum time to wait if stalled */
|
||||
|
||||
GLOBAL const char *direction; /* direction transfer is occurring */
|
||||
|
||||
GLOBAL sigjmp_buf toplevel; /* non-local goto stuff for cmd scanner */
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
|
||||
int foregroundproc(void);
|
||||
void alarmtimer(int);
|
||||
void progressmeter(int);
|
||||
sigfunc xsignal(int, sigfunc);
|
||||
sigfunc xsignal_restart(int, sigfunc, int);
|
||||
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
void psummary(int);
|
||||
void ptransfer(int);
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
|
||||
#ifdef NO_LONG_LONG
|
||||
# define LLF "%ld"
|
||||
# define LLFP(x) "%" x "ld"
|
||||
# define LLT long
|
||||
# define ULLF "%lu"
|
||||
# define ULLFP(x) "%" x "lu"
|
||||
# define ULLT unsigned long
|
||||
#else
|
||||
# define LLF "%lld"
|
||||
# define LLFP(x) "%" x "lld"
|
||||
# define LLT long long
|
||||
# define ULLF "%llu"
|
||||
# define ULLFP(x) "%" x "llu"
|
||||
# define ULLT unsigned long long
|
||||
#endif
|
318
usr.bin/ftp/ruserpass.c
Normal file
318
usr.bin/ftp/ruserpass.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
/* $NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ruserpass.c 8.4 (Berkeley) 4/27/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: ruserpass.c,v 1.33 2007/04/17 05:52:04 lukem Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ftp_var.h"
|
||||
|
||||
static int token(void);
|
||||
static FILE *cfile;
|
||||
|
||||
#define DEFAULT 1
|
||||
#define LOGIN 2
|
||||
#define PASSWD 3
|
||||
#define ACCOUNT 4
|
||||
#define MACDEF 5
|
||||
#define ID 10
|
||||
#define MACH 11
|
||||
|
||||
static char tokval[100];
|
||||
|
||||
static struct toktab {
|
||||
const char *tokstr;
|
||||
int tval;
|
||||
} toktab[] = {
|
||||
{ "default", DEFAULT },
|
||||
{ "login", LOGIN },
|
||||
{ "password", PASSWD },
|
||||
{ "passwd", PASSWD },
|
||||
{ "account", ACCOUNT },
|
||||
{ "machine", MACH },
|
||||
{ "macdef", MACDEF },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
int
|
||||
ruserpass(const char *host, char **aname, char **apass, char **aacct)
|
||||
{
|
||||
char *tmp;
|
||||
const char *mydomain;
|
||||
char myname[MAXHOSTNAMELEN + 1];
|
||||
int t, i, c, usedefault = 0;
|
||||
struct stat stb;
|
||||
|
||||
if (netrc[0] == '\0')
|
||||
return (0);
|
||||
cfile = fopen(netrc, "r");
|
||||
if (cfile == NULL) {
|
||||
if (errno != ENOENT)
|
||||
warn("Can't read `%s'", netrc);
|
||||
return (0);
|
||||
}
|
||||
if (gethostname(myname, sizeof(myname)) < 0)
|
||||
myname[0] = '\0';
|
||||
myname[sizeof(myname) - 1] = '\0';
|
||||
if ((mydomain = strchr(myname, '.')) == NULL)
|
||||
mydomain = "";
|
||||
next:
|
||||
while ((t = token()) > 0) switch(t) {
|
||||
|
||||
case DEFAULT:
|
||||
usedefault = 1;
|
||||
/* FALL THROUGH */
|
||||
|
||||
case MACH:
|
||||
if (!usedefault) {
|
||||
if ((t = token()) == -1)
|
||||
goto bad;
|
||||
if (t != ID)
|
||||
continue;
|
||||
/*
|
||||
* Allow match either for user's input host name
|
||||
* or official hostname. Also allow match of
|
||||
* incompletely-specified host in local domain.
|
||||
*/
|
||||
if (strcasecmp(host, tokval) == 0)
|
||||
goto match;
|
||||
if (strcasecmp(hostname, tokval) == 0)
|
||||
goto match;
|
||||
if ((tmp = strchr(hostname, '.')) != NULL &&
|
||||
strcasecmp(tmp, mydomain) == 0 &&
|
||||
strncasecmp(hostname, tokval, tmp-hostname) == 0 &&
|
||||
tokval[tmp - hostname] == '\0')
|
||||
goto match;
|
||||
if ((tmp = strchr(host, '.')) != NULL &&
|
||||
strcasecmp(tmp, mydomain) == 0 &&
|
||||
strncasecmp(host, tokval, tmp - host) == 0 &&
|
||||
tokval[tmp - host] == '\0')
|
||||
goto match;
|
||||
continue;
|
||||
}
|
||||
match:
|
||||
while ((t = token()) > 0 &&
|
||||
t != MACH && t != DEFAULT) switch(t) {
|
||||
|
||||
case LOGIN:
|
||||
if ((t = token()) == -1)
|
||||
goto bad;
|
||||
if (t) {
|
||||
if (*aname == NULL)
|
||||
*aname = ftp_strdup(tokval);
|
||||
else {
|
||||
if (strcmp(*aname, tokval))
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PASSWD:
|
||||
if ((*aname == NULL || strcmp(*aname, "anonymous")) &&
|
||||
fstat(fileno(cfile), &stb) >= 0 &&
|
||||
(stb.st_mode & 077) != 0) {
|
||||
warnx("Error: .netrc file is readable by others");
|
||||
warnx("Remove password or make file unreadable by others");
|
||||
goto bad;
|
||||
}
|
||||
if ((t = token()) == -1)
|
||||
goto bad;
|
||||
if (t && *apass == NULL)
|
||||
*apass = ftp_strdup(tokval);
|
||||
break;
|
||||
case ACCOUNT:
|
||||
if (fstat(fileno(cfile), &stb) >= 0
|
||||
&& (stb.st_mode & 077) != 0) {
|
||||
warnx("Error: .netrc file is readable by others");
|
||||
warnx("Remove account or make file unreadable by others");
|
||||
goto bad;
|
||||
}
|
||||
if ((t = token()) == -1)
|
||||
goto bad;
|
||||
if (t && *aacct == NULL)
|
||||
*aacct = ftp_strdup(tokval);
|
||||
break;
|
||||
case MACDEF:
|
||||
if (proxy) {
|
||||
(void)fclose(cfile);
|
||||
return (0);
|
||||
}
|
||||
while ((c = getc(cfile)) != EOF)
|
||||
if (c != ' ' && c != '\t')
|
||||
break;
|
||||
if (c == EOF || c == '\n') {
|
||||
fputs("Missing macdef name argument.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
if (macnum == 16) {
|
||||
fputs(
|
||||
"Limit of 16 macros have already been defined.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
tmp = macros[macnum].mac_name;
|
||||
*tmp++ = c;
|
||||
for (i = 0; i < 8 && (c = getc(cfile)) != EOF &&
|
||||
!isspace(c); ++i) {
|
||||
*tmp++ = c;
|
||||
}
|
||||
if (c == EOF) {
|
||||
fputs(
|
||||
"Macro definition missing null line terminator.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
*tmp = '\0';
|
||||
if (c != '\n') {
|
||||
while ((c = getc(cfile)) != EOF && c != '\n');
|
||||
}
|
||||
if (c == EOF) {
|
||||
fputs(
|
||||
"Macro definition missing null line terminator.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
if (macnum == 0) {
|
||||
macros[macnum].mac_start = macbuf;
|
||||
}
|
||||
else {
|
||||
macros[macnum].mac_start =
|
||||
macros[macnum-1].mac_end + 1;
|
||||
}
|
||||
tmp = macros[macnum].mac_start;
|
||||
while (tmp != macbuf + 4096) {
|
||||
if ((c = getc(cfile)) == EOF) {
|
||||
fputs(
|
||||
"Macro definition missing null line terminator.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
*tmp = c;
|
||||
if (*tmp == '\n') {
|
||||
if (tmp == macros[macnum].mac_start) {
|
||||
macros[macnum++].mac_end = tmp;
|
||||
break;
|
||||
} else if (*(tmp - 1) == '\0') {
|
||||
macros[macnum++].mac_end =
|
||||
tmp - 1;
|
||||
break;
|
||||
}
|
||||
*tmp = '\0';
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
if (tmp == macbuf + 4096) {
|
||||
fputs("4K macro buffer exceeded.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warnx("Unknown .netrc keyword `%s'", tokval);
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
if (t == -1)
|
||||
goto bad;
|
||||
(void)fclose(cfile);
|
||||
return (0);
|
||||
bad:
|
||||
(void)fclose(cfile);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
token(void)
|
||||
{
|
||||
char *cp;
|
||||
int c;
|
||||
struct toktab *t;
|
||||
|
||||
if (feof(cfile) || ferror(cfile))
|
||||
return (0);
|
||||
while ((c = getc(cfile)) != EOF &&
|
||||
(c == '\n' || c == '\t' || c == ' ' || c == ','))
|
||||
continue;
|
||||
if (c == EOF)
|
||||
return (0);
|
||||
cp = tokval;
|
||||
if (c == '"') {
|
||||
while ((c = getc(cfile)) != EOF && c != '"') {
|
||||
if (c == '\\')
|
||||
if ((c = getc(cfile)) == EOF)
|
||||
break;
|
||||
*cp++ = c;
|
||||
if (cp == tokval + sizeof(tokval)) {
|
||||
warnx("Token in .netrc too long");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*cp++ = c;
|
||||
while ((c = getc(cfile)) != EOF
|
||||
&& c != '\n' && c != '\t' && c != ' ' && c != ',') {
|
||||
if (c == '\\')
|
||||
if ((c = getc(cfile)) == EOF)
|
||||
break;
|
||||
*cp++ = c;
|
||||
if (cp == tokval + sizeof(tokval)) {
|
||||
warnx("Token in .netrc too long");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
*cp = 0;
|
||||
if (tokval[0] == 0)
|
||||
return (0);
|
||||
for (t = toktab; t->tokstr; t++)
|
||||
if (!strcmp(t->tokstr, tokval))
|
||||
return (t->tval);
|
||||
return (ID);
|
||||
}
|
608
usr.bin/ftp/ssl.c
Normal file
608
usr.bin/ftp/ssl.c
Normal file
|
@ -0,0 +1,608 @@
|
|||
/* $NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
* Copyright (c) 2008, 2010 Joerg Sonnenberger <joerg@NetBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: common.c,v 1.53 2007/12/19 00:26:36 des Exp $
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ssl.c,v 1.2 2012/12/24 22:12:28 christos Exp $");
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "ssl.h"
|
||||
|
||||
extern int quit_time, verbose, ftp_debug;
|
||||
extern FILE *ttyout;
|
||||
|
||||
struct fetch_connect {
|
||||
int sd; /* file/socket descriptor */
|
||||
char *buf; /* buffer */
|
||||
size_t bufsize; /* buffer size */
|
||||
size_t bufpos; /* position of buffer */
|
||||
size_t buflen; /* length of buffer contents */
|
||||
struct { /* data cached after an
|
||||
interrupted read */
|
||||
char *buf;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
size_t len;
|
||||
} cache;
|
||||
int issock;
|
||||
int iserr;
|
||||
int iseof;
|
||||
SSL *ssl; /* SSL handle */
|
||||
};
|
||||
|
||||
/*
|
||||
* Write a vector to a connection w/ timeout
|
||||
* Note: can modify the iovec.
|
||||
*/
|
||||
static ssize_t
|
||||
fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
||||
{
|
||||
struct timeval now, timeout, delta;
|
||||
fd_set writefds;
|
||||
ssize_t len, total;
|
||||
int r;
|
||||
|
||||
if (quit_time > 0) {
|
||||
FD_ZERO(&writefds);
|
||||
gettimeofday(&timeout, NULL);
|
||||
timeout.tv_sec += quit_time;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
while (iovcnt > 0) {
|
||||
while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) {
|
||||
FD_SET(conn->sd, &writefds);
|
||||
gettimeofday(&now, NULL);
|
||||
delta.tv_sec = timeout.tv_sec - now.tv_sec;
|
||||
delta.tv_usec = timeout.tv_usec - now.tv_usec;
|
||||
if (delta.tv_usec < 0) {
|
||||
delta.tv_usec += 1000000;
|
||||
delta.tv_sec--;
|
||||
}
|
||||
if (delta.tv_sec < 0) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
|
||||
if (r == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
if (conn->ssl != NULL)
|
||||
len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
|
||||
else
|
||||
len = writev(conn->sd, iov, iovcnt);
|
||||
if (len == 0) {
|
||||
/* we consider a short write a failure */
|
||||
/* XXX perhaps we shouldn't in the SSL case */
|
||||
errno = EPIPE;
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
total += len;
|
||||
while (iovcnt > 0 && len >= (ssize_t)iov->iov_len) {
|
||||
len -= iov->iov_len;
|
||||
iov++;
|
||||
iovcnt--;
|
||||
}
|
||||
if (iovcnt > 0) {
|
||||
iov->iov_len -= len;
|
||||
iov->iov_base = (char *)iov->iov_base + len;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to a connection w/ timeout
|
||||
*/
|
||||
static int
|
||||
fetch_write(struct fetch_connect *conn, const char *str, size_t len)
|
||||
{
|
||||
struct iovec iov[1];
|
||||
|
||||
iov[0].iov_base = (char *)__UNCONST(str);
|
||||
iov[0].iov_len = len;
|
||||
return fetch_writev(conn, iov, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a formatted line; optionally echo to terminal
|
||||
*/
|
||||
int
|
||||
fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
size_t len;
|
||||
char *msg;
|
||||
int r;
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vasprintf(&msg, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (msg == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = fetch_write(conn, msg, len);
|
||||
free(msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
fetch_fileno(struct fetch_connect *conn)
|
||||
{
|
||||
|
||||
return conn->sd;
|
||||
}
|
||||
|
||||
int
|
||||
fetch_error(struct fetch_connect *conn)
|
||||
{
|
||||
|
||||
return conn->iserr;
|
||||
}
|
||||
|
||||
static void
|
||||
fetch_clearerr(struct fetch_connect *conn)
|
||||
{
|
||||
|
||||
conn->iserr = 0;
|
||||
}
|
||||
|
||||
int
|
||||
fetch_flush(struct fetch_connect *conn)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (conn->issock) {
|
||||
#ifdef TCP_NOPUSH
|
||||
v = 0;
|
||||
setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
|
||||
#endif
|
||||
v = 1;
|
||||
setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
struct fetch_connect *
|
||||
fetch_open(const char *fname, const char *fmode)
|
||||
{
|
||||
struct fetch_connect *conn;
|
||||
int fd;
|
||||
|
||||
fd = open(fname, O_RDONLY); /* XXX: fmode */
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if ((conn = calloc(1, sizeof(*conn))) == NULL) {
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
conn->sd = fd;
|
||||
conn->issock = 0;
|
||||
return conn;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
struct fetch_connect *
|
||||
fetch_fdopen(int sd, const char *fmode)
|
||||
{
|
||||
struct fetch_connect *conn;
|
||||
#if defined(SO_NOSIGPIPE) || defined(TCP_NOPUSH)
|
||||
int opt = 1;
|
||||
#endif
|
||||
|
||||
if ((conn = calloc(1, sizeof(*conn))) == NULL)
|
||||
return NULL;
|
||||
|
||||
conn->sd = sd;
|
||||
conn->issock = 1;
|
||||
fcntl(sd, F_SETFD, FD_CLOEXEC);
|
||||
#ifdef SO_NOSIGPIPE
|
||||
setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
|
||||
#endif
|
||||
#ifdef TCP_NOPUSH
|
||||
setsockopt(sd, IPPROTO_TCP, TCP_NOPUSH, &opt, sizeof(opt));
|
||||
#endif
|
||||
return conn;
|
||||
}
|
||||
|
||||
int
|
||||
fetch_close(struct fetch_connect *conn)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if (conn != NULL) {
|
||||
fetch_flush(conn);
|
||||
SSL_free(conn->ssl);
|
||||
rv = close(conn->sd);
|
||||
if (rv < 0) {
|
||||
errno = rv;
|
||||
rv = EOF;
|
||||
}
|
||||
free(conn->cache.buf);
|
||||
free(conn->buf);
|
||||
free(conn);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define FETCH_READ_WAIT -2
|
||||
#define FETCH_READ_ERROR -1
|
||||
|
||||
static ssize_t
|
||||
fetch_ssl_read(SSL *ssl, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rlen;
|
||||
int ssl_err;
|
||||
|
||||
rlen = SSL_read(ssl, buf, len);
|
||||
if (rlen < 0) {
|
||||
ssl_err = SSL_get_error(ssl, rlen);
|
||||
if (ssl_err == SSL_ERROR_WANT_READ ||
|
||||
ssl_err == SSL_ERROR_WANT_WRITE) {
|
||||
return FETCH_READ_WAIT;
|
||||
}
|
||||
ERR_print_errors_fp(ttyout);
|
||||
return FETCH_READ_ERROR;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
fetch_nonssl_read(int sd, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rlen;
|
||||
|
||||
rlen = read(sd, buf, len);
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return FETCH_READ_WAIT;
|
||||
return FETCH_READ_ERROR;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache some data that was read from a socket but cannot be immediately
|
||||
* returned because of an interrupted system call.
|
||||
*/
|
||||
static int
|
||||
fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
|
||||
{
|
||||
|
||||
if (conn->cache.size < nbytes) {
|
||||
char *tmp = realloc(conn->cache.buf, nbytes);
|
||||
if (tmp == NULL)
|
||||
return -1;
|
||||
|
||||
conn->cache.buf = tmp;
|
||||
conn->cache.size = nbytes;
|
||||
}
|
||||
|
||||
memcpy(conn->cache.buf, src, nbytes);
|
||||
conn->cache.len = nbytes;
|
||||
conn->cache.pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
|
||||
{
|
||||
struct timeval now, timeout, delta;
|
||||
fd_set readfds;
|
||||
ssize_t rlen, total;
|
||||
size_t len;
|
||||
char *start, *buf;
|
||||
|
||||
if (quit_time > 0) {
|
||||
gettimeofday(&timeout, NULL);
|
||||
timeout.tv_sec += quit_time;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
start = buf = ptr;
|
||||
len = size * nmemb;
|
||||
|
||||
if (conn->cache.len > 0) {
|
||||
/*
|
||||
* The last invocation of fetch_read was interrupted by a
|
||||
* signal after some data had been read from the socket. Copy
|
||||
* the cached data into the supplied buffer before trying to
|
||||
* read from the socket again.
|
||||
*/
|
||||
total = (conn->cache.len < len) ? conn->cache.len : len;
|
||||
memcpy(buf, conn->cache.buf, total);
|
||||
|
||||
conn->cache.len -= total;
|
||||
conn->cache.pos += total;
|
||||
len -= total;
|
||||
buf += total;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
/*
|
||||
* The socket is non-blocking. Instead of the canonical
|
||||
* select() -> read(), we do the following:
|
||||
*
|
||||
* 1) call read() or SSL_read().
|
||||
* 2) if an error occurred, return -1.
|
||||
* 3) if we received data but we still expect more,
|
||||
* update our counters and loop.
|
||||
* 4) if read() or SSL_read() signaled EOF, return.
|
||||
* 5) if we did not receive any data but we're not at EOF,
|
||||
* call select().
|
||||
*
|
||||
* In the SSL case, this is necessary because if we
|
||||
* receive a close notification, we have to call
|
||||
* SSL_read() one additional time after we've read
|
||||
* everything we received.
|
||||
*
|
||||
* In the non-SSL case, it may improve performance (very
|
||||
* slightly) when reading small amounts of data.
|
||||
*/
|
||||
if (conn->ssl != NULL)
|
||||
rlen = fetch_ssl_read(conn->ssl, buf, len);
|
||||
else
|
||||
rlen = fetch_nonssl_read(conn->sd, buf, len);
|
||||
if (rlen == 0) {
|
||||
break;
|
||||
} else if (rlen > 0) {
|
||||
len -= rlen;
|
||||
buf += rlen;
|
||||
total += rlen;
|
||||
continue;
|
||||
} else if (rlen == FETCH_READ_ERROR) {
|
||||
if (errno == EINTR)
|
||||
fetch_cache_data(conn, start, total);
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(&readfds);
|
||||
while (!FD_ISSET(conn->sd, &readfds)) {
|
||||
FD_SET(conn->sd, &readfds);
|
||||
if (quit_time > 0) {
|
||||
gettimeofday(&now, NULL);
|
||||
if (!timercmp(&timeout, &now, >)) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
timersub(&timeout, &now, &delta);
|
||||
}
|
||||
errno = 0;
|
||||
if (select(conn->sd + 1, &readfds, NULL, NULL,
|
||||
quit_time > 0 ? &delta : NULL) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
#define MIN_BUF_SIZE 1024
|
||||
|
||||
/*
|
||||
* Read a line of text from a connection w/ timeout
|
||||
*/
|
||||
char *
|
||||
fetch_getln(char *str, int size, struct fetch_connect *conn)
|
||||
{
|
||||
size_t tmpsize;
|
||||
ssize_t len;
|
||||
char c;
|
||||
|
||||
if (conn->buf == NULL) {
|
||||
if ((conn->buf = malloc(MIN_BUF_SIZE)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
conn->iserr = 1;
|
||||
return NULL;
|
||||
}
|
||||
conn->bufsize = MIN_BUF_SIZE;
|
||||
}
|
||||
|
||||
if (conn->iserr || conn->iseof)
|
||||
return NULL;
|
||||
|
||||
if (conn->buflen - conn->bufpos > 0)
|
||||
goto done;
|
||||
|
||||
conn->buf[0] = '\0';
|
||||
conn->bufpos = 0;
|
||||
conn->buflen = 0;
|
||||
do {
|
||||
len = fetch_read(&c, sizeof(c), 1, conn);
|
||||
if (len == -1) {
|
||||
conn->iserr = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (len == 0) {
|
||||
conn->iseof = 1;
|
||||
break;
|
||||
}
|
||||
conn->buf[conn->buflen++] = c;
|
||||
if (conn->buflen == conn->bufsize) {
|
||||
char *tmp = conn->buf;
|
||||
tmpsize = conn->bufsize * 2 + 1;
|
||||
if ((tmp = realloc(tmp, tmpsize)) == NULL) {
|
||||
errno = ENOMEM;
|
||||
conn->iserr = 1;
|
||||
return NULL;
|
||||
}
|
||||
conn->buf = tmp;
|
||||
conn->bufsize = tmpsize;
|
||||
}
|
||||
} while (c != '\n');
|
||||
|
||||
if (conn->buflen == 0)
|
||||
return NULL;
|
||||
done:
|
||||
tmpsize = MIN(size - 1, (int)(conn->buflen - conn->bufpos));
|
||||
memcpy(str, conn->buf + conn->bufpos, tmpsize);
|
||||
str[tmpsize] = '\0';
|
||||
conn->bufpos += tmpsize;
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
|
||||
const char **errormsg)
|
||||
{
|
||||
size_t len;
|
||||
int rv;
|
||||
|
||||
if (fetch_getln(buf, buflen, conn) == NULL) {
|
||||
if (conn->iseof) { /* EOF */
|
||||
rv = -2;
|
||||
if (errormsg)
|
||||
*errormsg = "\nEOF received";
|
||||
} else { /* error */
|
||||
rv = -1;
|
||||
if (errormsg)
|
||||
*errormsg = "Error encountered";
|
||||
}
|
||||
fetch_clearerr(conn);
|
||||
return rv;
|
||||
}
|
||||
len = strlen(buf);
|
||||
if (buf[len - 1] == '\n') { /* clear any trailing newline */
|
||||
buf[--len] = '\0';
|
||||
} else if (len == buflen - 1) { /* line too long */
|
||||
while (1) {
|
||||
char c;
|
||||
ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn);
|
||||
if (rlen <= 0 || c == '\n')
|
||||
break;
|
||||
}
|
||||
if (errormsg)
|
||||
*errormsg = "Input line is too long";
|
||||
fetch_clearerr(conn);
|
||||
return -3;
|
||||
}
|
||||
if (errormsg)
|
||||
*errormsg = NULL;
|
||||
return len;
|
||||
}
|
||||
|
||||
void *
|
||||
fetch_start_ssl(int sock)
|
||||
{
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
int ret, ssl_err;
|
||||
|
||||
/* Init the SSL library and context */
|
||||
if (!SSL_library_init()){
|
||||
fprintf(ttyout, "SSL library init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSL_load_error_strings();
|
||||
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
if (ssl == NULL){
|
||||
fprintf(ttyout, "SSL context creation failed\n");
|
||||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
SSL_set_fd(ssl, sock);
|
||||
while ((ret = SSL_connect(ssl)) == -1) {
|
||||
ssl_err = SSL_get_error(ssl, ret);
|
||||
if (ssl_err != SSL_ERROR_WANT_READ &&
|
||||
ssl_err != SSL_ERROR_WANT_WRITE) {
|
||||
ERR_print_errors_fp(ttyout);
|
||||
SSL_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftp_debug && verbose) {
|
||||
X509 *cert;
|
||||
X509_NAME *name;
|
||||
char *str;
|
||||
|
||||
fprintf(ttyout, "SSL connection established using %s\n",
|
||||
SSL_get_cipher(ssl));
|
||||
cert = SSL_get_peer_certificate(ssl);
|
||||
name = X509_get_subject_name(cert);
|
||||
str = X509_NAME_oneline(name, 0, 0);
|
||||
fprintf(ttyout, "Certificate subject: %s\n", str);
|
||||
free(str);
|
||||
name = X509_get_issuer_name(cert);
|
||||
str = X509_NAME_oneline(name, 0, 0);
|
||||
fprintf(ttyout, "Certificate issuer: %s\n", str);
|
||||
free(str);
|
||||
}
|
||||
|
||||
return ssl;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
fetch_set_ssl(struct fetch_connect *conn, void *ssl)
|
||||
{
|
||||
conn->ssl = ssl;
|
||||
}
|
62
usr.bin/ftp/ssl.h
Normal file
62
usr.bin/ftp/ssl.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/* $NetBSD: ssl.h,v 1.1 2012/12/21 18:07:36 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef WITH_SSL
|
||||
|
||||
#define FETCH struct fetch_connect
|
||||
struct fetch_connect;
|
||||
|
||||
int fetch_printf(struct fetch_connect *, const char *fmt, ...);
|
||||
int fetch_fileno(struct fetch_connect *);
|
||||
int fetch_error(struct fetch_connect *);
|
||||
int fetch_flush(struct fetch_connect *);
|
||||
struct fetch_connect *fetch_open(const char *, const char *);
|
||||
struct fetch_connect *fetch_fdopen(int, const char *);
|
||||
int fetch_close(struct fetch_connect *);
|
||||
ssize_t fetch_read(void *, size_t, size_t, struct fetch_connect *);
|
||||
char *fetch_getln(char *, int, struct fetch_connect *);
|
||||
int fetch_getline(struct fetch_connect *, char *, size_t, const char **);
|
||||
void fetch_set_ssl(struct fetch_connect *, void *);
|
||||
void *fetch_start_ssl(int);
|
||||
|
||||
#else /* !WITH_SSL */
|
||||
|
||||
#define FETCH FILE
|
||||
|
||||
#define fetch_printf fprintf
|
||||
#define fetch_fileno fileno
|
||||
#define fetch_error ferror
|
||||
#define fetch_flush fflush
|
||||
#define fetch_open fopen
|
||||
#define fetch_fdopen fdopen
|
||||
#define fetch_close fclose
|
||||
#define fetch_read fread
|
||||
#define fetch_getln fgets
|
||||
#define fetch_getline get_line
|
||||
#define fetch_set_ssl(a, b)
|
||||
|
||||
#endif /* !WITH_SSL */
|
1543
usr.bin/ftp/util.c
Normal file
1543
usr.bin/ftp/util.c
Normal file
File diff suppressed because it is too large
Load diff
38
usr.bin/ftp/version.h
Normal file
38
usr.bin/ftp/version.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* $NetBSD: version.h,v 1.83 2013/02/06 16:37:20 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999-2009 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Luke Mewburn.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FTP_PRODUCT
|
||||
#define FTP_PRODUCT "NetBSD-ftp"
|
||||
#endif
|
||||
|
||||
#ifndef FTP_VERSION
|
||||
#define FTP_VERSION "20121224"
|
||||
#endif
|
Loading…
Reference in a new issue