]>
diplodocus.org Git - nmh/blob - uip/ftpsbr.c
3 * ftpsbr.c -- simple FTP client library
7 * This code is Copyright (c) 2002, by the authors of nmh. See the
8 * COPYRIGHT file in the root directory of the nmh distribution for
9 * complete copyright information.
15 #ifdef HAVE_ARPA_FTP_H
16 # include <arpa/ftp.h>
19 #define v_debug debugsw
20 #define v_verbose verbosw
22 static int ftp_fd
= NOTOK
;
23 static int data_fd
= NOTOK
;
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
37 # define h_addr h_addr_list[0]
40 #define inaddr_copy(hp,sin) \
41 memcpy((char *) &((sin)->sin_addr), (hp)->h_addr, (hp)->h_length)
43 #define start_tcp_client(sock,priv) \
44 socket (AF_INET, SOCK_STREAM, 0)
46 #define join_tcp_server(fd, sock) \
47 connect ((fd), (struct sockaddr *) (sock), sizeof *(sock))
52 struct hostent
*gethostbystring ();
53 int ftp_get (char *, char *, char *, char *, char *, char *, int, int);
54 int ftp_trans (char *, char *, char *, char *, char *, char *, char *, int, int);
59 static int start_tcp_server (struct sockaddr_in
*, int, int, int);
60 static void _asnprintf (char *, int, char *, va_list);
61 static int ftp_quit (void);
62 static int ftp_read (char *, char *, char *, int);
63 static int initconn (void);
64 static int dataconn (void);
65 static int command (int arg1
, ...);
66 static int vcommand (int, va_list);
67 static int getreply (int, int);
71 start_tcp_server (struct sockaddr_in
*sock
, int backlog
, int opt1
, int opt2
)
75 if ((sd
= socket (AF_INET
, SOCK_STREAM
, 0)) == NOTOK
)
78 if (bind (sd
, (struct sockaddr
*) sock
, sizeof *sock
) == NOTOK
) {
92 #define join_tcp_client(fd,sock) \
93 accept ((fd), (struct sockaddr *) (sock), \
94 (__len__ = sizeof *(sock), &__len__))
96 #define read_tcp_socket read
97 #define write_tcp_socket write
98 #define close_tcp_socket close
101 _asnprintf (char *bp
, int len_bp
, char *what
, va_list ap
)
109 fmt
= va_arg (ap
, char *);
112 vsnprintf(bp
, len_bp
, fmt
, ap
);
122 snprintf (bp
, len_bp
, " %s: ", what
);
127 if ((s
= strerror(eindex
)))
128 strncpy (bp
, s
, len_bp
);
130 snprintf (bp
, len_bp
, "Error %d", eindex
);
139 ftp_get (char *host
, char *user
, char *password
, char *cwd
,
140 char *remote
, char *local
, int ascii
, int stayopen
)
142 return ftp_trans (host
, user
, password
, cwd
, remote
, local
,
143 "RETR", ascii
, stayopen
);
148 ftp_trans (char *host
, char *user
, char *password
, char *cwd
, char *remote
,
149 char *local
, char *cmd
, int ascii
, int stayopen
)
154 result
= ftp_quit ();
159 if (ftp_fd
== NOTOK
) {
160 struct sockaddr_in in_socket
;
161 register struct hostent
*hp
;
162 register struct servent
*sp
;
164 if ((sp
= getservbyname ("ftp", "tcp")) == NULL
) {
165 fprintf (stderr
, "tcp/ftp: unknown service");
168 if ((hp
= gethostbystring (host
)) == NULL
) {
169 fprintf (stderr
, "%s: unknown host\n", host
);
172 in_socket
.sin_family
= hp
->h_addrtype
;
173 inaddr_copy (hp
, &in_socket
);
174 in_socket
.sin_port
= sp
->s_port
;
176 if ((ftp_fd
= start_tcp_client ((struct sockaddr_in
*) NULL
, 0))
181 if (join_tcp_server (ftp_fd
, &in_socket
) == NOTOK
) {
183 close_tcp_socket (ftp_fd
), ftp_fd
= NOTOK
;
189 fprintf (stdout
, "Connected to %s\n", host
);
194 if ((result
= command (0, "USER %s", user
)) == CONTINUE
)
195 result
= command (1, "PASS %s", password
);
196 if (result
!= COMPLETE
) {
206 if (cwd
&& ((result
= command (0, "CWD %s", cwd
)) != COMPLETE
207 && result
!= CONTINUE
)) {
212 if (command (1, ascii
? "TYPE A" : "TYPE I") != COMPLETE
) {
217 result
= ftp_read (remote
, local
, cmd
, ascii
);
220 if (result
!= OK
|| !stayopen
)
235 n
= command (1, "QUIT");
236 close_tcp_socket (ftp_fd
), ftp_fd
= NOTOK
;
237 return (n
== 0 || n
== COMPLETE
? OK
: NOTOK
);
241 ftp_read (char *remote
, char *local
, char *cmd
, int ascii
)
243 int istdio
= 0, istore
;
245 int expectingreply
= 0;
249 if (initconn () == NOTOK
)
253 if (command (-1, *remote
? "%s %s" : "%s", cmd
, remote
) != PRELIM
)
257 if (dataconn () == NOTOK
) {
261 if (data_fd
!= NOTOK
)
262 close_tcp_socket (data_fd
), data_fd
= NOTOK
;
269 istore
= !strcmp (cmd
, "STOR");
271 if ((istdio
= !strcmp (local
, "-")))
272 fp
= istore
? stdin
: stdout
;
274 if ((fp
= fopen (local
, istore
? "r" : "w")) == NULL
) {
284 if (!(out
= fdopen (data_fd
, "w"))) {
289 while ((c
= getc (fp
)) != EOF
) {
292 if (putc (c
, out
) == EOF
) {
304 while ((cc
= fread (buffer
, sizeof *buffer
, sizeof buffer
, fp
)) > 0)
305 if (write_tcp_socket (data_fd
, buffer
, cc
) != cc
) {
306 perror ("write_tcp_socket");
310 close_tcp_socket (data_fd
), data_fd
= NOTOK
;
318 if (!(in
= fdopen (data_fd
, "r"))) {
323 while ((c
= getc (in
)) != EOF
) {
325 switch (c
= getc (in
)) {
339 if (putc (c
, fp
) == EOF
) {
351 while ((cc
= read_tcp_socket (data_fd
, buffer
, sizeof buffer
)) > 0)
352 if (fwrite (buffer
, sizeof *buffer
, cc
, fp
) == 0) {
357 perror ("read_tcp_socket");
361 close_tcp_socket (data_fd
), data_fd
= NOTOK
;
369 return (getreply (1, 0) == COMPLETE
? OK
: NOTOK
);
373 #define UC(b) (((int) b) & 0xff)
379 register char *a
, *p
;
380 struct sockaddr_in in_socket
;
382 if (getsockname (ftp_fd
, (struct sockaddr
*) &in_socket
,
383 (len
= sizeof(in_socket
), &len
)) == NOTOK
) {
384 perror ("getsockname");
387 in_socket
.sin_port
= 0;
388 if ((data_fd
= start_tcp_server (&in_socket
, 1, 0, 0)) == NOTOK
) {
389 perror ("start_tcp_server");
393 if (getsockname (data_fd
, (struct sockaddr
*) &in_socket
,
394 (len
= sizeof in_socket
, &len
)) == NOTOK
) {
395 perror ("getsockname");
399 a
= (char *) &in_socket
.sin_addr
;
400 p
= (char *) &in_socket
.sin_port
;
402 if (command (1, "PORT %d,%d,%d,%d,%d,%d",
403 UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
404 UC(p
[0]), UC(p
[1])) == COMPLETE
)
414 struct sockaddr_in in_socket
;
416 if ((fd
= join_tcp_client (data_fd
, &in_socket
)) == NOTOK
) {
417 perror ("join_tcp_client");
420 close_tcp_socket (data_fd
);
428 command (int arg1
, ...)
434 val
= vcommand (arg1
, ap
);
441 vcommand (int complete
, va_list ap
)
449 _asnprintf (buffer
, sizeof(buffer
), NULL
, ap
);
451 fprintf (stderr
, "<--- %s\n", buffer
);
453 strcat (buffer
, "\r\n");
454 len
= strlen (buffer
);
456 if (write_tcp_socket (ftp_fd
, buffer
, len
) != len
) {
457 perror ("write_tcp_socket");
461 return (getreply (complete
, !strcmp (buffer
, "QUIT")));
466 getreply (int complete
, int expecteof
)
469 register int code
, dig
, n
;
474 code
= dig
= n
= continuation
= 0;
480 if (read_tcp_socket (ftp_fd
, &c
, 1) < 1) {
484 perror ("read_tcp_socket");
489 *bp
++ = c
!= '\r' ? c
: '\0';
494 code
= code
* 10 + (c
- '0');
495 else /* XXX: naughty FTP... */
500 if (dig
== 4 && c
== '-')
507 fprintf (stderr
, "---> %s\n", buffer
);
514 fprintf (stdout
, "%s\n", buffer
);
519 if ((complete
== -1 && n
!= PRELIM
)
520 || (complete
== 0 && n
!= CONTINUE
&& n
!= COMPLETE
)
521 || (complete
== 1 && n
!= COMPLETE
))
522 fprintf (stderr
, "%s\n", buffer
);