X-Git-Url: http://git.marmaro.de/?p=mmh;a=blobdiff_plain;f=uip%2Fftpsbr.c;h=7d6d72b4722281bd21c9f49c5c343eaea4623f5b;hp=525554e77ae304fd8c5d30e70df6ef9bc6079880;hb=714b5c530ece27ea2835a313013f5b770163403c;hpb=3d251965606d6a6e47897504594f84d12e3e292a diff --git a/uip/ftpsbr.c b/uip/ftpsbr.c index 525554e..7d6d72b 100644 --- a/uip/ftpsbr.c +++ b/uip/ftpsbr.c @@ -1,9 +1,10 @@ - /* - * ftpsbr.c -- simple FTP client library - * - * $Id$ - */ +** ftpsbr.c -- simple FTP client library +** +** This code is Copyright (c) 2002, by the authors of nmh. See the +** COPYRIGHT file in the root directory of the nmh distribution for +** complete copyright information. +*/ #include #include @@ -12,8 +13,8 @@ # include #endif -#define v_debug debugsw -#define v_verbose verbosw +#define v_debug debugsw +#define v_verbose verbosw static int ftp_fd = NOTOK; static int data_fd = NOTOK; @@ -29,494 +30,491 @@ extern int v_verbose; #include #include -#if !defined(h_addr) -# define h_addr h_addr_list[0] -#endif - -#define inaddr_copy(hp,sin) \ - memcpy((char *) &((sin)->sin_addr), (hp)->h_addr, (hp)->h_length) +#define start_tcp_client(res) \ + socket(res->ai_family, res->ai_socktype, res->ai_protocol) -#define start_tcp_client(sock,priv) \ - socket (AF_INET, SOCK_STREAM, 0) - -#define join_tcp_server(fd, sock) \ - connect ((fd), (struct sockaddr *) (sock), sizeof *(sock)) +#define join_tcp_server(fd, sock, len) \ + connect((fd), (struct sockaddr *) (sock), len) /* - * prototypes - */ -struct hostent *gethostbystring (); -int ftp_get (char *, char *, char *, char *, char *, char *, int, int); -int ftp_trans (char *, char *, char *, char *, char *, char *, char *, int, int); +** prototypes +*/ +int ftp_get(char *, char *, char *, char *, char *, char *, int, int); +int ftp_trans(char *, char *, char *, char *, char *, char *, char *, + int, int); /* - * static prototypes - */ -static int start_tcp_server (struct sockaddr_in *, int, int, int); -static void _asnprintf (char *, int, char *, va_list); -static int ftp_quit (void); -static int ftp_read (char *, char *, char *, int); -static int initconn (void); -static int dataconn (void); -static int command (int arg1, ...); -static int vcommand (int, va_list); -static int getreply (int, int); +** static prototypes +*/ +static int start_tcp_server(struct sockaddr_in *, int, int, int); +static void _asnprintf(char *, int, char *, va_list); +static int ftp_quit(void); +static int ftp_read(char *, char *, char *, int); +static int initconn(void); +static int dataconn(void); +static int command(int arg1, ...); +static int vcommand(int, va_list); +static int getreply(int, int); static int -start_tcp_server (struct sockaddr_in *sock, int backlog, int opt1, int opt2) +start_tcp_server(struct sockaddr_in *sock, int backlog, int opt1, int opt2) { - int eindex, sd; + int eindex, sd; - if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) - return NOTOK; + if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == NOTOK) + return NOTOK; - if (bind (sd, (struct sockaddr *) sock, sizeof *sock) == NOTOK) { - eindex = errno; - close (sd); - errno = eindex; - } else { - listen (sd, backlog); - } + if (bind(sd, (struct sockaddr *) sock, sizeof *sock) == NOTOK) { + eindex = errno; + close(sd); + errno = eindex; + } else { + listen(sd, backlog); + } - return sd; + return sd; } static int __len__; -#define join_tcp_client(fd,sock) \ - accept ((fd), (struct sockaddr *) (sock), \ +#define join_tcp_client(fd,sock) \ + accept((fd), (struct sockaddr *) (sock), \ (__len__ = sizeof *(sock), &__len__)) -#define read_tcp_socket read -#define write_tcp_socket write -#define close_tcp_socket close +#define read_tcp_socket read +#define write_tcp_socket write +#define close_tcp_socket close static void -_asnprintf (char *bp, int len_bp, char *what, va_list ap) +_asnprintf(char *bp, int len_bp, char *what, va_list ap) { - int eindex, len; - char *fmt; + int eindex, len; + char *fmt; - eindex = errno; + eindex = errno; - *bp = '\0'; - fmt = va_arg (ap, char *); + *bp = '\0'; + fmt = va_arg(ap, char *); - if (fmt) { - vsnprintf(bp, len_bp, fmt, ap); - len = strlen(bp); - bp += len; - len_bp -= len; - } + if (fmt) { + vsnprintf(bp, len_bp, fmt, ap); + len = strlen(bp); + bp += len; + len_bp -= len; + } - if (what) { - char *s; + if (what) { + char *s; - if (*what) { - snprintf (bp, len_bp, " %s: ", what); - len = strlen (bp); - bp += len; - len_bp -= len; + if (*what) { + snprintf(bp, len_bp, " %s: ", what); + len = strlen(bp); + bp += len; + len_bp -= len; + } + if ((s = strerror(eindex))) + strncpy(bp, s, len_bp); + else + snprintf(bp, len_bp, "Error %d", eindex); + bp += strlen(bp); } - if ((s = strerror(eindex))) - strncpy (bp, s, len_bp); - else - snprintf (bp, len_bp, "Error %d", eindex); - bp += strlen (bp); - } - errno = eindex; + errno = eindex; } int -ftp_get (char *host, char *user, char *password, char *cwd, - char *remote, char *local, int ascii, int stayopen) +ftp_get(char *host, char *user, char *password, char *cwd, + char *remote, char *local, int ascii, int stayopen) { - return ftp_trans (host, user, password, cwd, remote, local, - "RETR", ascii, stayopen); + return ftp_trans(host, user, password, cwd, remote, local, + "RETR", ascii, stayopen); } int -ftp_trans (char *host, char *user, char *password, char *cwd, char *remote, - char *local, char *cmd, int ascii, int stayopen) +ftp_trans(char *host, char *user, char *password, char *cwd, char *remote, + char *local, char *cmd, int ascii, int stayopen) { - int result; + int result; - if (stayopen <= 0) { - result = ftp_quit (); - if (host == NULL) - return result; - } + if (stayopen <= 0) { + result = ftp_quit(); + if (host == NULL) + return result; + } - if (ftp_fd == NOTOK) { - struct sockaddr_in in_socket; - register struct hostent *hp; - register struct servent *sp; + if (ftp_fd == NOTOK) { + struct addrinfo hints, *res; - if ((sp = getservbyname ("ftp", "tcp")) == NULL) { - fprintf (stderr, "tcp/ftp: unknown service"); - return NOTOK; - } - if ((hp = gethostbystring (host)) == NULL) { - fprintf (stderr, "%s: unknown host\n", host); - return NOTOK; - } - in_socket.sin_family = hp->h_addrtype; - inaddr_copy (hp, &in_socket); - in_socket.sin_port = sp->s_port; - - if ((ftp_fd = start_tcp_client ((struct sockaddr_in *) NULL, 0)) - == NOTOK) { - perror (host); - return NOTOK; - } - if (join_tcp_server (ftp_fd, &in_socket) == NOTOK) { - perror (host); - close_tcp_socket (ftp_fd), ftp_fd = NOTOK; - return NOTOK; - } - getreply (1, 0); + memset(&hints, 0, sizeof(hints)); +#ifdef AI_ADDRCONFIG + hints.ai_flags = AI_ADDRCONFIG; +#endif + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + + result = getaddrinfo(host, "ftp", &hints, &res); + + if (result) { + fprintf(stderr, "%s/ftp: %s\n", + host, gai_strerror(result)); + return NOTOK; + } - if (v_verbose) { - fprintf (stdout, "Connected to %s\n", host); - fflush (stdout); + if ((ftp_fd = start_tcp_client(res)) == NOTOK) { + perror(host); + freeaddrinfo(res); + return NOTOK; + } + if (join_tcp_server(ftp_fd, res->ai_addr, res->ai_addrlen) + == NOTOK) { + perror(host); + freeaddrinfo(res); + close_tcp_socket(ftp_fd), ftp_fd = NOTOK; + return NOTOK; + } + freeaddrinfo(res); + getreply(1, 0); + + if (v_verbose) { + fprintf(stdout, "Connected to %s\n", host); + fflush(stdout); + } + + if (user) { + if ((result = command (0, "USER %s", user)) + == CONTINUE) + result = command(1, "PASS %s", password); + if (result != COMPLETE) { + result = NOTOK; + goto out; + } + } + + if (remote == NULL) + return OK; } - if (user) { - if ((result = command (0, "USER %s", user)) == CONTINUE) - result = command (1, "PASS %s", password); - if (result != COMPLETE) { + if (cwd && ((result = command (0, "CWD %s", cwd)) != COMPLETE + && result != CONTINUE)) { result = NOTOK; goto out; - } } - if (remote == NULL) - return OK; - } - - if (cwd && ((result = command (0, "CWD %s", cwd)) != COMPLETE - && result != CONTINUE)) { - result = NOTOK; - goto out; - } - - if (command (1, ascii ? "TYPE A" : "TYPE I") != COMPLETE) { - result = NOTOK; - goto out; - } + if (command(1, ascii ? "TYPE A" : "TYPE I") != COMPLETE) { + result = NOTOK; + goto out; + } - result = ftp_read (remote, local, cmd, ascii); + result = ftp_read(remote, local, cmd, ascii); out: ; - if (result != OK || !stayopen) - ftp_quit (); + if (result != OK || !stayopen) + ftp_quit(); - return result; + return result; } static int -ftp_quit (void) +ftp_quit(void) { - int n; + int n; - if (ftp_fd == NOTOK) - return OK; + if (ftp_fd == NOTOK) + return OK; - n = command (1, "QUIT"); - close_tcp_socket (ftp_fd), ftp_fd = NOTOK; - return (n == 0 || n == COMPLETE ? OK : NOTOK); + n = command(1, "QUIT"); + close_tcp_socket(ftp_fd), ftp_fd = NOTOK; + return (n == 0 || n == COMPLETE ? OK : NOTOK); } static int -ftp_read (char *remote, char *local, char *cmd, int ascii) +ftp_read(char *remote, char *local, char *cmd, int ascii) { - int istdio = 0, istore; - register int cc; - int expectingreply = 0; - char buffer[BUFSIZ]; - FILE *fp = NULL; + int istdio = 0, istore; + register int cc; + int expectingreply = 0; + char buffer[BUFSIZ]; + FILE *fp = NULL; - if (initconn () == NOTOK) - goto bad; + if (initconn() == NOTOK) + goto bad; - v_noise = v_verbose; - if (command (-1, *remote ? "%s %s" : "%s", cmd, remote) != PRELIM) - goto bad; + v_noise = v_verbose; + if (command(-1, *remote ? "%s %s" : "%s", cmd, remote) != PRELIM) + goto bad; - expectingreply++; - if (dataconn () == NOTOK) { + expectingreply++; + if (dataconn() == NOTOK) { bad: ; - if (fp && !istdio) - fclose (fp); - if (data_fd != NOTOK) - close_tcp_socket (data_fd), data_fd = NOTOK; - if (expectingreply) - getreply (-2, 0); + if (fp && !istdio) + fclose(fp); + if (data_fd != NOTOK) + close_tcp_socket(data_fd), data_fd = NOTOK; + if (expectingreply) + getreply(-2, 0); + + return NOTOK; + } - return NOTOK; - } + istore = !strcmp(cmd, "STOR"); - istore = !strcmp (cmd, "STOR"); + if ((istdio = !strcmp(local, "-"))) + fp = istore ? stdin : stdout; + else + if ((fp = fopen(local, istore ? "r" : "w")) == NULL) { + perror(local); + goto bad; + } - if ((istdio = !strcmp (local, "-"))) - fp = istore ? stdin : stdout; - else - if ((fp = fopen (local, istore ? "r" : "w")) == NULL) { - perror (local); - goto bad; - } + if (istore) { + if (ascii) { + int c; + FILE *out; - if (istore) { - if (ascii) { - int c; - FILE *out; + if (!(out = fdopen(data_fd, "w"))) { + perror("fdopen"); + goto bad; + } - if (!(out = fdopen (data_fd, "w"))) { - perror ("fdopen"); - goto bad; - } - - while ((c = getc (fp)) != EOF) { - if (c == '\n') - putc ('\r', out); - if (putc (c, out) == EOF) { - perror ("putc"); - fclose (out); - data_fd = NOTOK; - goto bad; - } - } + while ((c = getc(fp)) != EOF) { + if (c == '\n') + putc('\r', out); + if (putc(c, out) == EOF) { + perror("putc"); + fclose(out); + data_fd = NOTOK; + goto bad; + } + } - fclose (out); - data_fd = NOTOK; - } - else { - while ((cc = fread (buffer, sizeof *buffer, sizeof buffer, fp)) > 0) - if (write_tcp_socket (data_fd, buffer, cc) != cc) { - perror ("write_tcp_socket"); - goto bad; + fclose(out); + data_fd = NOTOK; + } else { + while ((cc = fread(buffer, sizeof *buffer, + sizeof buffer, fp)) > 0) + if (write_tcp_socket(data_fd, buffer, cc) + != cc) { + perror("write_tcp_socket"); + goto bad; + } + + close_tcp_socket(data_fd), data_fd = NOTOK; } + } else { + if (ascii) { + int c; + FILE *in; + + if (!(in = fdopen(data_fd, "r"))) { + perror("fdopen"); + goto bad; + } - close_tcp_socket (data_fd), data_fd = NOTOK; - } - } - else { - if (ascii) { - int c; - FILE *in; - - if (!(in = fdopen (data_fd, "r"))) { - perror ("fdopen"); - goto bad; - } - - while ((c = getc (in)) != EOF) { - if (c == '\r') - switch (c = getc (in)) { - case EOF: - case '\0': - c = '\r'; - break; - - case '\n': - break; - - default: - putc ('\r', fp); - break; + while ((c = getc(in)) != EOF) { + if (c == '\r') + switch (c = getc(in)) { + case EOF: + case '\0': + c = '\r'; + break; + + case '\n': + break; + + default: + putc('\r', fp); + break; + } + + if (putc(c, fp) == EOF) { + perror("putc"); + fclose(in); + data_fd = NOTOK; + goto bad; + } } - if (putc (c, fp) == EOF) { - perror ("putc"); - fclose (in); - data_fd = NOTOK; - goto bad; - } - } + fclose(in); + data_fd = NOTOK; + } else { + while ((cc = read_tcp_socket(data_fd, buffer, + sizeof buffer)) > 0) + if (fwrite(buffer, sizeof *buffer, cc, fp) + == 0) { + perror("fwrite"); + goto bad; + } + if (cc < 0) { + perror("read_tcp_socket"); + goto bad; + } - fclose (in); - data_fd = NOTOK; - } - else { - while ((cc = read_tcp_socket (data_fd, buffer, sizeof buffer)) > 0) - if (fwrite (buffer, sizeof *buffer, cc, fp) == 0) { - perror ("fwrite"); - goto bad; + close_tcp_socket(data_fd), data_fd = NOTOK; } - if (cc < 0) { - perror ("read_tcp_socket"); - goto bad; - } - - close_tcp_socket (data_fd), data_fd = NOTOK; } - } - if (!istdio) - fclose (fp); + if (!istdio) + fclose(fp); - v_noise = v_verbose; - return (getreply (1, 0) == COMPLETE ? OK : NOTOK); + v_noise = v_verbose; + return (getreply(1, 0) == COMPLETE ? OK : NOTOK); } -#define UC(b) (((int) b) & 0xff) +#define UC(b) (((int) b) & 0xff) static int -initconn (void) +initconn(void) { - int len; - register char *a, *p; - struct sockaddr_in in_socket; + int len; + register char *a, *p; + struct sockaddr_in in_socket; - if (getsockname (ftp_fd, (struct sockaddr *) &in_socket, - (len = sizeof(in_socket), &len)) == NOTOK) { - perror ("getsockname"); - return NOTOK; - } - in_socket.sin_port = 0; - if ((data_fd = start_tcp_server (&in_socket, 1, 0, 0)) == NOTOK) { - perror ("start_tcp_server"); - return NOTOK; - } + if (getsockname(ftp_fd, (struct sockaddr *) &in_socket, + (len = sizeof(in_socket), &len)) == NOTOK) { + perror("getsockname"); + return NOTOK; + } + in_socket.sin_port = 0; + if ((data_fd = start_tcp_server(&in_socket, 1, 0, 0)) == NOTOK) { + perror("start_tcp_server"); + return NOTOK; + } - if (getsockname (data_fd, (struct sockaddr *) &in_socket, - (len = sizeof in_socket, &len)) == NOTOK) { - perror ("getsockname"); - return NOTOK; - } + if (getsockname(data_fd, (struct sockaddr *) &in_socket, + (len = sizeof in_socket, &len)) == NOTOK) { + perror("getsockname"); + return NOTOK; + } - a = (char *) &in_socket.sin_addr; - p = (char *) &in_socket.sin_port; + a = (char *) &in_socket.sin_addr; + p = (char *) &in_socket.sin_port; - if (command (1, "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])) == COMPLETE) - return OK; + if (command(1, "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])) == COMPLETE) + return OK; - return NOTOK; + return NOTOK; } static int -dataconn (void) +dataconn(void) { - int fd; - struct sockaddr_in in_socket; - - if ((fd = join_tcp_client (data_fd, &in_socket)) == NOTOK) { - perror ("join_tcp_client"); - return NOTOK; - } - close_tcp_socket (data_fd); - data_fd = fd; + int fd; + struct sockaddr_in in_socket; + + if ((fd = join_tcp_client(data_fd, &in_socket)) == NOTOK) { + perror("join_tcp_client"); + return NOTOK; + } + close_tcp_socket(data_fd); + data_fd = fd; - return OK; + return OK; } static int -command (int arg1, ...) +command(int arg1, ...) { - int val; - va_list ap; + int val; + va_list ap; - va_start (ap, arg1); - val = vcommand (arg1, ap); - va_end (ap); + va_start(ap, arg1); + val = vcommand(arg1, ap); + va_end(ap); - return val; + return val; } static int -vcommand (int complete, va_list ap) +vcommand(int complete, va_list ap) { - int len; - char buffer[BUFSIZ]; + int len; + char buffer[BUFSIZ]; - if (ftp_fd == NOTOK) - return NOTOK; + if (ftp_fd == NOTOK) + return NOTOK; - _asnprintf (buffer, sizeof(buffer), NULL, ap); - if (v_debug) - fprintf (stderr, "<--- %s\n", buffer); + _asnprintf(buffer, sizeof(buffer), NULL, ap); + if (v_debug) + fprintf(stderr, "<--- %s\n", buffer); - strcat (buffer, "\r\n"); - len = strlen (buffer); + strcat(buffer, "\r\n"); + len = strlen(buffer); - if (write_tcp_socket (ftp_fd, buffer, len) != len) { - perror ("write_tcp_socket"); - return NOTOK; - } + if (write_tcp_socket(ftp_fd, buffer, len) != len) { + perror("write_tcp_socket"); + return NOTOK; + } - return (getreply (complete, !strcmp (buffer, "QUIT"))); + return(getreply(complete, !strcmp(buffer, "QUIT"))); } static int -getreply (int complete, int expecteof) +getreply(int complete, int expecteof) { - for (;;) { - register int code, dig, n; - int continuation; - register char *bp; - char buffer[BUFSIZ]; + for (;;) { + register int code, dig, n; + int continuation; + register char *bp; + char buffer[BUFSIZ]; - code = dig = n = continuation = 0; - bp = buffer; + code = dig = n = continuation = 0; + bp = buffer; - for (;;) { - char c; - - if (read_tcp_socket (ftp_fd, &c, 1) < 1) { - if (expecteof) - return OK; - - perror ("read_tcp_socket"); - return DONE; - } - if (c == '\n') - break; - *bp++ = c != '\r' ? c : '\0'; - - dig++; - if (dig < 4) { - if (isdigit(c)) - code = code * 10 + (c - '0'); - else /* XXX: naughty FTP... */ - if (isspace (c)) - continuation++; - } - else - if (dig == 4 && c == '-') - continuation++; - if (n == 0) - n = c; - } + for (;;) { + unsigned char c; - if (v_debug) - fprintf (stderr, "---> %s\n", buffer); - if (continuation) - continue; + if (read_tcp_socket(ftp_fd, &c, 1) < 1) { + if (expecteof) + return OK; - n -= '0'; + perror("read_tcp_socket"); + return DONE; + } + if (c == '\n') + break; + *bp++ = c != '\r' ? c : '\0'; + + dig++; + if (dig < 4) { + if (isdigit(c)) + code = code * 10 + (c - '0'); + else if (isspace(c)) + /* XXX: naughty FTP... */ + continuation++; + } else + if (dig == 4 && c == '-') + continuation++; + if (n == 0) + n = c; + } - if (v_noise) { - fprintf (stdout, "%s\n", buffer); - fflush (stdout); - v_noise = 0; - } - else - if ((complete == -1 && n != PRELIM) - || (complete == 0 && n != CONTINUE && n != COMPLETE) - || (complete == 1 && n != COMPLETE)) - fprintf (stderr, "%s\n", buffer); + if (v_debug) + fprintf(stderr, "---> %s\n", buffer); + if (continuation) + continue; + + n -= '0'; - return n; - } + if (v_noise) { + fprintf(stdout, "%s\n", buffer); + fflush(stdout); + v_noise = 0; + } else + if ((complete == -1 && n != PRELIM) + || (complete == 0 && n != CONTINUE && n != COMPLETE) + || (complete == 1 && n != COMPLETE)) + fprintf(stderr, "%s\n", buffer); + + return n; + } }