1 /* ftpsbr.c - simple FTP client library (why doesn't BSD have one?!?) */
4 static char ident[] = "@(#)$Id: ftpsbr.c,v 1.13 1993/08/25 17:25:27 jromine Exp $";
12 #undef NULLVP /* stdio.h */
23 static int command(int arg1, ...);
28 static int ftp_quit(), ftp_read(), initconn(),
29 dataconn(), _command(), getreply();
33 #define v_debug debugsw
34 #define v_verbose verbosw
37 static int ftp_fd = NOTOK;
38 static int data_fd = NOTOK;
47 #if defined(SYS5) && defined(AUX)
48 #define u_short ushort
52 #include <sys/types.h>
53 #include <sys/socket.h>
54 #include <netinet/in.h>
57 #if defined(BIND) && !defined(h_addr)
58 #define h_addr h_addr_list[0]
61 #define inaddr_copy(hp,sin) \
62 bcopy ((hp) -> h_addr, (char *) &((sin) -> sin_addr), (hp) -> h_length)
65 struct hostent *gethostbystring ();
72 extern char *sys_errlist[];
76 #define start_tcp_client(sock,priv) \
77 socket (AF_INET, SOCK_STREAM, 0)
79 #define join_tcp_server(fd, sock) \
80 connect ((fd), (struct sockaddr *) (sock), sizeof *(sock))
85 static int start_tcp_server (sock, backlog, opt1, opt2)
86 struct sockaddr_in *sock;
94 if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
97 if (bind (sd, (struct sockaddr *) sock, sizeof *sock) == NOTOK) {
103 (void) listen (sd, backlog);
109 #define join_tcp_client(fd,sock) \
110 accept ((fd), (struct sockaddr *) (sock), \
111 (__len__ = sizeof *(sock), &__len__))
114 #define read_tcp_socket read
115 #define write_tcp_socket write
116 #define close_tcp_socket close
120 static void _asprintf (bp, what, ap) /* fmt, args, ... */
131 fmt = va_arg (ap, char *);
140 bzero ((char *) &iob, sizeof iob);
143 iob._flag = _IOWRT | _IOSTRG;
144 #if !defined(vax) && !defined(pyr) && !defined(sequent)
145 iob._ptr = (unsigned char *) bp;
150 _doprnt (fmt, ap, &iob);
151 (void) putc ('\0', &iob);
153 (void) vsprintf (bp, fmt, ap);
161 (void) sprintf (bp, " %s: ", what);
164 if (0 < eindex && eindex < sys_nerr)
165 (void) strcpy (bp, sys_errlist[eindex]);
167 (void) sprintf (bp, "Error %d", eindex);
176 int ftp_get (host, user, password, cwd, remote, local, ascii, stayopen)
186 return ftp_trans (host, user, password, cwd, remote, local, "RETR", ascii,
192 int ftp_trans (host, user, password, cwd, remote, local, cmd, ascii,
207 result = ftp_quit ();
212 if (ftp_fd == NOTOK) {
213 struct sockaddr_in in_socket;
214 register struct hostent *hp;
215 register struct servent *sp;
217 if ((sp = getservbyname ("ftp", "tcp")) == NULL) {
218 fprintf (stderr, "tcp/ftp: unknown service");
221 if ((hp = gethostbystring (host)) == NULL) {
222 fprintf (stderr, "%s: unknown host\n", host);
225 in_socket.sin_family = hp -> h_addrtype;
226 inaddr_copy (hp, &in_socket);
227 in_socket.sin_port = sp -> s_port;
229 if ((ftp_fd = start_tcp_client ((struct sockaddr_in *) NULL, 0))
234 if (join_tcp_server (ftp_fd, &in_socket) == NOTOK) {
236 (void) close_tcp_socket (ftp_fd), ftp_fd = NOTOK;
239 (void) getreply (1, 0);
242 fprintf (stdout, "Connected to %s\n", host);
243 (void) fflush (stdout);
247 if ((result = command (0, "USER %s", user)) == CONTINUE)
248 result = command (1, "PASS %s", password);
249 if (result != COMPLETE) {
259 if (cwd && ((result = command (0, "CWD %s", cwd)) != COMPLETE
260 && result != CONTINUE)) {
265 if (command (1, ascii ? "TYPE A" : "TYPE I") != COMPLETE) {
270 result = ftp_read (remote, local, cmd, ascii);
273 if (result != OK || !stayopen)
281 static int ftp_quit ()
288 n = command (1, "QUIT");
290 (void) close_tcp_socket (ftp_fd), ftp_fd = NOTOK;
292 return (n == 0 || n == COMPLETE ? OK : NOTOK);
297 static int ftp_read (remote, local, cmd, ascii)
306 int expectingreply = 0;
310 if (initconn () == NOTOK)
314 if (command (-1, *remote ? "%s %s" : "%s", cmd, remote) != PRELIM)
318 if (dataconn () == NOTOK) {
322 if (data_fd != NOTOK)
323 (void) close_tcp_socket (data_fd), data_fd = NOTOK;
325 (void) getreply (-2, 0);
330 istore = !strcmp (cmd, "STOR");
332 if (istdio = !strcmp (local, "-"))
333 fp = istore ? stdin : stdout;
335 if ((fp = fopen (local, istore ? "r" : "w")) == NULL) {
345 if (!(out = fdopen (data_fd, "w"))) {
350 while ((c = getc (fp)) != EOF) {
352 (void) putc ('\r', out);
353 if (putc (c, out) == EOF) {
365 while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, fp)) >0)
366 if (write_tcp_socket (data_fd, buffer, cc) != cc) {
367 perror ("write_tcp_socket");
371 (void) close_tcp_socket (data_fd), data_fd = NOTOK;
379 if (!(in = fdopen (data_fd, "r"))) {
384 while ((c = getc (in)) != EOF) {
386 switch (c = getc (in)) {
396 (void) putc ('\r', fp);
400 if (putc (c, fp) == EOF) {
412 while ((cc = read_tcp_socket (data_fd, buffer, sizeof buffer)) > 0)
413 if (fwrite (buffer, sizeof *buffer, cc, fp) == 0) {
418 perror ("read_tcp_socket");
422 (void) close_tcp_socket (data_fd), data_fd = NOTOK;
430 return (getreply (1, 0) == COMPLETE ? OK : NOTOK);
435 static int initconn ()
440 struct sockaddr_in in_socket;
442 if (getsockname (ftp_fd, (struct sockaddr *) &in_socket,
443 (len = sizeof in_socket, &len)) == NOTOK) {
444 perror ("getsockname");
447 in_socket.sin_port = 0;
448 if ((data_fd = start_tcp_server (&in_socket, 1, 0, 0)) == NOTOK) {
449 perror ("start_tcp_server");
453 if (getsockname (data_fd, (struct sockaddr *) &in_socket,
454 (len = sizeof in_socket, &len)) == NOTOK) {
455 perror ("getsockname");
459 a = (char *) &in_socket.sin_addr;
460 p = (char *) &in_socket.sin_port;
462 #define UC(b) (((int) b) & 0xff)
463 if (command (1, "PORT %d,%d,%d,%d,%d,%d",
464 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
465 UC(p[0]), UC(p[1])) == COMPLETE)
473 static int dataconn ()
476 struct sockaddr_in in_socket;
478 if ((fd = join_tcp_client (data_fd, &in_socket)) == NOTOK) {
479 perror ("join_tcp_client");
482 (void) close_tcp_socket (data_fd);
492 static int command (int arg1, ...)
499 val = _command (arg1, ap);
506 static int command (va_alist)
514 val = va_arg (ap, int);
515 val = _command (val, ap);
523 static int _command (complete, ap)
533 _asprintf (buffer, NULLCP, ap);
535 fprintf (stderr, "<--- %s\n", buffer);
537 (void) strcat (buffer, "\r\n");
538 len = strlen (buffer);
540 if (write_tcp_socket (ftp_fd, buffer, len) != len) {
541 perror ("write_tcp_socket");
545 return (getreply (complete, !strcmp (buffer, "QUIT")));
550 static int command (complete, fmt)
554 return command (complete, fmt);
560 static int getreply (complete, expecteof)
572 code = dig = n = continuation = 0;
578 if (read_tcp_socket (ftp_fd, &c, 1) < 1) {
582 perror ("read_tcp_socket");
587 *bp++ = c != '\r' ? c : '\0';
592 code = code * 10 + (c - '0');
593 else /* XXX: naughty FTP... */
598 if (dig == 4 && c == '-')
605 fprintf (stderr, "---> %s\n", buffer);
612 fprintf (stdout, "%s\n", buffer);
613 (void) fflush (stdout);
617 if ((complete == -1 && n != PRELIM)
618 || (complete == 0 && n != CONTINUE && n != COMPLETE)
619 || (complete == 1 && n != COMPLETE))
620 fprintf (stderr, "%s\n", buffer);