static char sccsid
[] = "@(#)ftp.c 4.9 (Berkeley) %G%";
struct sockaddr_in hisctladdr
;
struct sockaddr_in data_addr
;
struct sockaddr_in myctladdr
;
register struct hostent
*hp
;
bzero((char *)&hisctladdr
, sizeof (hisctladdr
));
hp
= gethostbyname(host
);
static struct hostent def
;
static struct in_addr defaddr
;
static char namebuf
[128];
defaddr
.s_addr
= inet_addr(host
);
if (defaddr
.s_addr
== -1) {
fprintf(stderr
, "%s: Unknown host.\n", host
);
def
.h_addr
= (char *)&defaddr
;
def
.h_length
= sizeof (struct in_addr
);
def
.h_addrtype
= AF_INET
;
hisctladdr
.sin_family
= hp
->h_addrtype
;
s
= socket(hp
->h_addrtype
, SOCK_STREAM
, 0, 0);
if (bind(s
, (char *)&hisctladdr
, sizeof (hisctladdr
), 0) < 0) {
bcopy(hp
->h_addr
, (char *)&hisctladdr
.sin_addr
, hp
->h_length
);
hisctladdr
.sin_port
= port
;
if (connect(s
, (char *)&hisctladdr
, sizeof (hisctladdr
), 0) < 0) {
len
= sizeof (myctladdr
);
if (getsockname(s
, (char *)&myctladdr
, &len
) < 0) {
perror("ftp: getsockname");
if (cin
== NULL
|| cout
== NULL
) {
fprintf(stderr
, "ftp: fdopen failed.\n");
printf("Connected to %s.\n", hp
->h_name
);
(void) getreply(0); /* read startup message from server */
return ((struct hostent
*)0);
ruserpass(hp
->h_name
, &user
, &pass
);
n
= command("USER %s", user
);
n
= command("PASS %s", pass
);
printf("Account: "); (void) fflush(stdout
);
(void) fgets(acct
, sizeof(acct
) - 1, stdin
);
acct
[strlen(acct
) - 1] = '\0';
n
= command("ACCT %s", acct
);
fprintf(stderr
, "Login failed.\n");
_doprnt(fmt
, &args
, stdout
);
perror ("No control connection for command");
_doprnt(fmt
, &args
, cout
);
return (getreply(!strcmp(fmt
, "QUIT")));
int originalcode
= 0, continuation
= 0;
while ((c
= getc(cin
)) != '\n') {
if (verbose
&& c
!= '\r' ||
if (dig
< 4 && isdigit(c
))
code
= code
* 10 + (c
- '0');
if (dig
== 4 && c
== '-')
if (verbose
|| n
== '5') {
if (continuation
&& code
!= originalcode
) {
if (expecteof
|| empty(cin
))
t
.tv_sec
= t
.tv_usec
= 0;
(void) select(20, &mask
, 0, 0, &t
);
sendrequest(cmd
, local
, remote
)
char *cmd
, *local
, *remote
;
FILE *fin
, *dout
, *popen();
int (*closefunc
)(), pclose(), fclose(), (*oldintr
)();
long bytes
= 0, hashbytes
= sizeof (buf
);
struct timeval start
, stop
;
oldintr
= signal(SIGINT
, abortsend
);
if (strcmp(local
, "-") == 0)
else if (*local
== '|') {
fin
= popen(local
+ 1, "r");
if (fstat(fileno(fin
), &st
) < 0 ||
(st
.st_mode
&S_IFMT
) != S_IFREG
) {
fprintf(stderr
, "%s: not a plain file.", local
);
if (command("%s %s", cmd
, remote
) != PRELIM
)
if (command("%s", cmd
) != PRELIM
)
gettimeofday(&start
, (struct timezone
*)0);
while ((c
= read(fileno (fin
), buf
, sizeof (buf
))) > 0) {
if ((d
= write(fileno (dout
), buf
, c
)) < 0)
while ((c
= getc(fin
)) != EOF
) {
while (hash
&& (bytes
>= hashbytes
)) {
hashbytes
+= sizeof (buf
);
gettimeofday(&stop
, (struct timezone
*)0);
if (bytes
> 0 && verbose
)
ptransfer("sent", bytes
, &start
, &stop
);
(void) close(data
), data
= -1;
if (closefunc
!= NULL
&& fin
!= NULL
)
recvrequest(cmd
, local
, remote
, mode
)
char *cmd
, *local
, *remote
, *mode
;
FILE *fout
, *din
, *popen();
int (*closefunc
)(), pclose(), fclose(), (*oldintr
)();
long bytes
= 0, hashbytes
= sizeof (buf
);
struct timeval start
, stop
;
oldintr
= signal(SIGINT
, abortrecv
);
if (strcmp(local
, "-") && *local
!= '|')
if (access(local
, 2) < 0) {
char *dir
= rindex(local
, '/');
if (access(dir
? dir
: ".", 2) < 0) {
if (command("%s %s", cmd
, remote
) != PRELIM
)
if (command("%s", cmd
) != PRELIM
)
if (strcmp(local
, "-") == 0)
else if (*local
== '|') {
fout
= popen(local
+ 1, "w");
fout
= fopen(local
, mode
);
gettimeofday(&start
, (struct timezone
*)0);
while ((c
= read(fileno(din
), buf
, sizeof (buf
))) > 0) {
if ((d
= write(fileno(fout
), buf
, c
)) < 0)
while ((c
= getc(din
)) != EOF
) {
while (hash
&& (bytes
>= hashbytes
)) {
hashbytes
+= sizeof (buf
);
if ((c
= getc(din
)) != '\n') {
gettimeofday(&stop
, (struct timezone
*)0);
if (bytes
> 0 && verbose
)
ptransfer("received", bytes
, &start
, &stop
);
(void) close(data
), data
= -1;
if (closefunc
!= NULL
&& fout
!= NULL
)
* Need to start a listen on the data channel
* before we send the command, otherwise the
* server's connect may fail.
static int sendport
= -1;
data_addr
.sin_port
= 0; /* let system pick one */
data
= socket(AF_INET
, SOCK_STREAM
, 0, 0);
if (setsockopt(data
, SOL_SOCKET
, SO_REUSEADDR
, 0, 0) < 0) {
perror("ftp: setsockopt (resuse address)");
if (bind(data
, (char *)&data_addr
, sizeof (data_addr
), 0) < 0) {
if (options
& SO_DEBUG
&&
setsockopt(data
, SOL_SOCKET
, SO_DEBUG
, 0, 0) < 0)
perror("ftp: setsockopt (ignored)");
len
= sizeof (data_addr
);
if (getsockname(data
, (char *)&data_addr
, &len
) < 0) {
perror("ftp: getsockname");
if (listen(data
, 1) < 0) {
a
= (char *)&data_addr
.sin_addr
;
p
= (char *)&data_addr
.sin_port
;
#define UC(b) (((int)b)&0xff)
command("PORT %d,%d,%d,%d,%d,%d",
UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
if (result
== ERROR
&& sendport
== -1) {
return (result
!= COMPLETE
);
(void) close(data
), data
= -1;
int s
, fromlen
= sizeof (from
);
s
= accept(data
, &from
, &fromlen
, 0);
(void) close(data
), data
= -1;
if (*mode
== 'w' && linger
)
(void) setsockopt(s
, SOL_SOCKET
, SO_LINGER
, &linger
,
return (fdopen(data
, mode
));
ptransfer(direction
, bytes
, t0
, t1
)
ms
= (td
.tv_sec
* 1000) + (td
.tv_usec
/ 1000);
#define nz(x) ((x) == 0 ? 1 : (x))
bs
= ((bytes
* NBBY
* 1000) / (float) nz(ms
)) / NBBY
;
printf("%ld bytes %s in %d.%02d seconds (%.2g Kbytes/s)\n",
bytes
, direction
, td
.tv_sec
, td
.tv_usec
/ 10000, bs
/ 1024.);
struct timeval
*tsum
, *t0
;
tsum
->tv_sec
+= t0
->tv_sec
;
tsum
->tv_usec
+= t0
->tv_usec
;
if (tsum
->tv_usec
> 1000000)
tsum
->tv_sec
++, tsum
->tv_usec
-= 1000000;
struct timeval
*tdiff
, *t1
, *t0
;
tdiff
->tv_sec
= t1
->tv_sec
- t0
->tv_sec
;
tdiff
->tv_usec
= t1
->tv_usec
- t0
->tv_usec
;
tdiff
->tv_sec
--, tdiff
->tv_usec
+= 1000000;