📄 ftp.c
字号:
if (bytes > 0)
ptransfer(0);
(void)signal(SIGINT, oldintr);
(void)signal(SIGINFO, oldinti);
}
/*
* Need to start a listen on the data channel before we send the command,
* otherwise the server's connect may fail.
*/
int
initconn()
{
char *p, *a;
int result, len, tmpno = 0;
int on = 1;
int a0, a1, a2, a3, p0, p1;
int ports;
if (passivemode) {
data = socket(AF_INET, SOCK_STREAM, 0);
if (data < 0) {
warn("socket");
return (1);
}
if ((options & SO_DEBUG) &&
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
sizeof(on)) < 0)
warn("setsockopt (ignored)");
if (command("PASV") != COMPLETE) {
puts("Passive mode refused.");
goto bad;
}
/*
* What we've got at this point is a string of comma
* separated one-byte unsigned integer values.
* The first four are the an IP address. The fifth is
* the MSB of the port number, the sixth is the LSB.
* From that we'll prepare a sockaddr_in.
*/
if (sscanf(pasv, "%d,%d,%d,%d,%d,%d",
&a0, &a1, &a2, &a3, &p0, &p1) != 6) {
puts(
"Passive mode address scan failure. Shouldn't happen!");
goto bad;
}
memset(&data_addr, 0, sizeof(data_addr));
data_addr.sin_family = AF_INET;
a = (char *)&data_addr.sin_addr.s_addr;
a[0] = a0 & 0xff;
a[1] = a1 & 0xff;
a[2] = a2 & 0xff;
a[3] = a3 & 0xff;
p = (char *)&data_addr.sin_port;
p[0] = p0 & 0xff;
p[1] = p1 & 0xff;
if (connect(data, (struct sockaddr *)&data_addr,
sizeof(data_addr)) < 0) {
warn("connect");
goto bad;
}
#ifdef IP_TOS
on = IPTOS_THROUGHPUT;
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
#endif
return (0);
}
noport:
data_addr = myctladdr;
if (sendport)
data_addr.sin_port = 0; /* let system pick one */
if (data != -1)
(void)close(data);
data = socket(AF_INET, SOCK_STREAM, 0);
if (data < 0) {
warn("socket");
if (tmpno)
sendport = 1;
return (1);
}
if (!sendport)
if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
sizeof(on)) < 0) {
warn("setsockopt (reuse address)");
goto bad;
}
#ifdef IP_PORTRANGE
ports = restricted_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE, (char *)&ports,
sizeof(ports)) < 0)
warn("setsockopt PORTRANGE (ignored)");
#endif
if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) {
warn("bind");
goto bad;
}
if (options & SO_DEBUG &&
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
sizeof(on)) < 0)
warn("setsockopt (ignored)");
len = sizeof(data_addr);
if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
warn("getsockname");
goto bad;
}
if (listen(data, 1) < 0)
warn("listen");
if (sendport) {
a = (char *)&data_addr.sin_addr;
p = (char *)&data_addr.sin_port;
#define UC(b) (((int)b)&0xff)
result =
command("PORT %d,%d,%d,%d,%d,%d",
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
UC(p[0]), UC(p[1]));
if (result == ERROR && sendport == -1) {
sendport = 0;
tmpno = 1;
goto noport;
}
return (result != COMPLETE);
}
if (tmpno)
sendport = 1;
#ifdef IP_TOS
on = IPTOS_THROUGHPUT;
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
#endif
return (0);
bad:
(void)close(data), data = -1;
if (tmpno)
sendport = 1;
return (1);
}
FILE *
dataconn(lmode)
const char *lmode;
{
struct sockaddr_in from;
int s, fromlen, tos;
fromlen = sizeof(from);
if (passivemode)
return (fdopen(data, lmode));
s = accept(data, (struct sockaddr *) &from, &fromlen);
if (s < 0) {
warn("accept");
(void)close(data), data = -1;
return (NULL);
}
(void)close(data);
data = s;
#ifdef IP_TOS
tos = IPTOS_THROUGHPUT;
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
warn("setsockopt TOS (ignored)");
#endif
return (fdopen(data, lmode));
}
void
psummary(notused)
int notused;
{
if (bytes > 0)
ptransfer(1);
}
void
psabort(notused)
int notused;
{
alarmtimer(0);
abrtflag++;
}
void
pswitch(flag)
int flag;
{
sig_t oldintr;
static struct comvars {
int connect;
char name[MAXHOSTNAMELEN];
struct sockaddr_in mctl;
struct sockaddr_in hctl;
FILE *in;
FILE *out;
int tpe;
int curtpe;
int cpnd;
int sunqe;
int runqe;
int mcse;
int ntflg;
char nti[17];
char nto[17];
int mapflg;
char mi[MAXPATHLEN];
char mo[MAXPATHLEN];
} proxstruct, tmpstruct;
struct comvars *ip, *op;
abrtflag = 0;
oldintr = signal(SIGINT, psabort);
if (flag) {
if (proxy)
return;
ip = &tmpstruct;
op = &proxstruct;
proxy++;
} else {
if (!proxy)
return;
ip = &proxstruct;
op = &tmpstruct;
proxy = 0;
}
ip->connect = connected;
connected = op->connect;
if (hostname) {
(void)strncpy(ip->name, hostname, sizeof(ip->name) - 1);
ip->name[sizeof(ip->name) - 1] = '\0';
} else
ip->name[0] = '\0';
hostname = op->name;
ip->hctl = hisctladdr;
hisctladdr = op->hctl;
ip->mctl = myctladdr;
myctladdr = op->mctl;
ip->in = cin;
cin = op->in;
ip->out = cout;
cout = op->out;
ip->tpe = type;
type = op->tpe;
ip->curtpe = curtype;
curtype = op->curtpe;
ip->cpnd = cpend;
cpend = op->cpnd;
ip->sunqe = sunique;
sunique = op->sunqe;
ip->runqe = runique;
runique = op->runqe;
ip->mcse = mcase;
mcase = op->mcse;
ip->ntflg = ntflag;
ntflag = op->ntflg;
(void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
(ip->nti)[sizeof(ip->nti) - 1] = '\0';
(void)strcpy(ntin, op->nti);
(void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
(ip->nto)[sizeof(ip->nto) - 1] = '\0';
(void)strcpy(ntout, op->nto);
ip->mapflg = mapflag;
mapflag = op->mapflg;
(void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1);
(ip->mi)[sizeof(ip->mi) - 1] = '\0';
(void)strcpy(mapin, op->mi);
(void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1);
(ip->mo)[sizeof(ip->mo) - 1] = '\0';
(void)strcpy(mapout, op->mo);
(void)signal(SIGINT, oldintr);
if (abrtflag) {
abrtflag = 0;
(*oldintr)(SIGINT);
}
}
void
abortpt(notused)
int notused;
{
alarmtimer(0);
putchar('\n');
(void)fflush(stdout);
ptabflg++;
mflag = 0;
abrtflag = 0;
longjmp(ptabort, 1);
}
void
proxtrans(cmd, local, remote)
const char *cmd, *local, *remote;
{
sig_t oldintr;
int prox_type, nfnd;
volatile int secndflag;
char *cmd2;
fd_set mask;
#ifdef __GNUC__ /* XXX: to shut up gcc warnings */
(void)&oldintr;
(void)&cmd2;
#endif
oldintr = NULL;
secndflag = 0;
if (strcmp(cmd, "RETR"))
cmd2 = "RETR";
else
cmd2 = runique ? "STOU" : "STOR";
if ((prox_type = type) == 0) {
if (unix_server && unix_proxy)
prox_type = TYPE_I;
else
prox_type = TYPE_A;
}
if (curtype != prox_type)
changetype(prox_type, 1);
if (command("PASV") != COMPLETE) {
puts("proxy server does not support third party transfers.");
return;
}
pswitch(0);
if (!connected) {
puts("No primary connection.");
pswitch(1);
code = -1;
return;
}
if (curtype != prox_type)
changetype(prox_type, 1);
if (command("PORT %s", pasv) != COMPLETE) {
pswitch(1);
return;
}
if (setjmp(ptabort))
goto abort;
oldintr = signal(SIGINT, abortpt);
if (command("%s %s", cmd, remote) != PRELIM) {
(void)signal(SIGINT, oldintr);
pswitch(1);
return;
}
sleep(2);
pswitch(1);
secndflag++;
if (command("%s %s", cmd2, local) != PRELIM)
goto abort;
ptflag++;
(void)getreply(0);
pswitch(0);
(void)getreply(0);
(void)signal(SIGINT, oldintr);
pswitch(1);
ptflag = 0;
printf("local: %s remote: %s\n", local, remote);
return;
abort:
(void)signal(SIGINT, SIG_IGN);
ptflag = 0;
if (strcmp(cmd, "RETR") && !proxy)
pswitch(1);
else if (!strcmp(cmd, "RETR") && proxy)
pswitch(0);
if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
if (command("%s %s", cmd2, local) != PRELIM) {
pswitch(0);
if (cpend)
abort_remote((FILE *) NULL);
}
pswitch(1);
if (ptabflg)
code = -1;
(void)signal(SIGINT, oldintr);
return;
}
if (cpend)
abort_remote((FILE *) NULL);
pswitch(!proxy);
if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
if (command("%s %s", cmd2, local) != PRELIM) {
pswitch(0);
if (cpend)
abort_remote((FILE *) NULL);
pswitch(1);
if (ptabflg)
code = -1;
(void)signal(SIGINT, oldintr);
return;
}
}
if (cpend)
abort_remote((FILE *) NULL);
pswitch(!proxy);
if (cpend) {
FD_ZERO(&mask);
FD_SET(fileno(cin), &mask);
if ((nfnd = empty(&mask, 10)) <= 0) {
if (nfnd < 0) {
warn("abort");
}
if (ptabflg)
code = -1;
lostpeer();
}
(void)getreply(0);
(void)getreply(0);
}
if (proxy)
pswitch(0);
pswitch(1);
if (ptabflg)
code = -1;
(void)signal(SIGINT, oldintr);
}
void
reset(argc, argv)
int argc;
char *argv[];
{
fd_set mask;
int nfnd = 1;
FD_ZERO(&mask);
while (nfnd > 0) {
FD_SET(fileno(cin), &mask);
if ((nfnd = empty(&mask, 0)) < 0) {
warn("reset");
code = -1;
lostpeer();
}
else if (nfnd) {
(void)getreply(0);
}
}
}
char *
gunique(local)
const char *local;
{
static char new[MAXPATHLEN];
char *cp = strrchr(local, '/');
int d, count=0;
char ext = '1';
if (cp)
*cp = '\0';
d = access(cp == local ? "/" : cp ? local : ".", W_OK);
if (cp)
*cp = '/';
if (d < 0) {
warn("local: %s", local);
return ((char *) 0);
}
(void)strcpy(new, local);
cp = new + strlen(new);
*cp++ = '.';
while (!d) {
if (++count == 100) {
puts("runique: can't find unique file name.");
return ((char *) 0);
}
*cp++ = ext;
*cp = '\0';
if (ext == '9')
ext = '0';
else
ext++;
if ((d = access(new, F_OK)) < 0)
break;
if (ext != '0')
cp--;
else if (*(cp - 2) == '.')
*(cp - 1) = '1';
else {
*(cp - 2) = *(cp - 2) + 1;
cp--;
}
}
return (new);
}
void
abort_remote(din)
FILE *din;
{
char buf[BUFSIZ];
int nfnd;
fd_set mask;
if (cout == NULL) {
warnx("Lost control connection for abort.");
if (ptabflg)
code = -1;
lostpeer();
return;
}
/*
* send IAC in urgent mode instead of DM because 4.3BSD places oob mark
* after urgent byte rather than before as is protocol now
*/
sprintf(buf, "%c%c%c", IAC, IP, IAC);
if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
warn("abort");
fprintf(cout, "%cABOR\r\n", DM);
(void)fflush(cout);
FD_ZERO(&mask);
FD_SET(fileno(cin), &mask);
if (din) {
FD_SET(fileno(din), &mask);
}
if ((nfnd = empty(&mask, 10)) <= 0) {
if (nfnd < 0) {
warn("abort");
}
if (ptabflg)
code = -1;
lostpeer();
}
if (din && FD_ISSET(fileno(din), &mask)) {
while (read(fileno(din), buf, BUFSIZ) > 0)
/* LOOP */;
}
if (getreply(0) == ERROR && code == 552) {
/* 552 needed for nic style abort */
(void)getreply(0);
}
(void)getreply(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -