diff options
Diffstat (limited to 'lib/libftpio')
-rw-r--r-- | lib/libftpio/Makefile | 34 | ||||
-rw-r--r-- | lib/libftpio/ftp.errors | 45 | ||||
-rw-r--r-- | lib/libftpio/ftpio.3 | 260 | ||||
-rw-r--r-- | lib/libftpio/ftpio.c | 1069 | ||||
-rw-r--r-- | lib/libftpio/ftpio.h | 71 |
5 files changed, 0 insertions, 1479 deletions
diff --git a/lib/libftpio/Makefile b/lib/libftpio/Makefile deleted file mode 100644 index 2082ec5..0000000 --- a/lib/libftpio/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# $FreeBSD$ - -.include <bsd.own.mk> - -LIB= ftpio -SHLIB_MAJOR= 8 - -SRCS= ftpio.c ftperr.c -INCS= ftpio.h -CFLAGS+= -I${.CURDIR} -Wall -MAN= ftpio.3 -CLEANFILES= ftperr.c - -.if ${MK_INET6_SUPPORT} != "no" -CFLAGS+= -DINET6 -.endif - -WARNS?= 2 - -ftperr.c: ftp.errors - @echo '#include <stdio.h>' > ${.TARGET} - @echo '#include "ftpio.h"' >> ${.TARGET} - @echo "struct ftperr ftpErrList[] = {" \ >> ${.TARGET} - @cat ${.ALLSRC} \ - | grep -v ^# \ - | sort \ - | while read NUM STRING; do \ - echo " { $${NUM}, \"$${STRING}\" },"; \ - done >> ${.TARGET} - @echo "};" >> ${.TARGET} - @echo -n "int const ftpErrListLength = " >> ${.TARGET} - @echo "sizeof(ftpErrList) / sizeof(*ftpErrList);" >> ${.TARGET} - -.include <bsd.lib.mk> diff --git a/lib/libftpio/ftp.errors b/lib/libftpio/ftp.errors deleted file mode 100644 index c03eeac..0000000 --- a/lib/libftpio/ftp.errors +++ /dev/null @@ -1,45 +0,0 @@ -# $FreeBSD$ -# -# This list is taken from RFC 959. -# It probably needs a going over. -# -110 Restart marker reply -120 Service ready in a few minutes -125 Data connection already open; transfer starting -150 File status okay; about to open data connection -200 Command okay -202 Command not implemented, superfluous at this site -211 System status, or system help reply -212 Directory status -213 File status -214 Help message -215 Set system type -220 Service ready for new user -221 Service closing control connection -225 Data connection open; no transfer in progress -226 Requested file action successful -227 Entering Passive Mode -229 Entering Extended Passive Mode -230 User logged in, proceed -250 Requested file action okay, completed -257 File/directory created -331 User name okay, need password -332 Need account for login -350 Requested file action pending further information -421 Service not available, closing control connection -425 Can't open data connection -426 Connection closed; transfer aborted -450 File unavailable (e.g., file busy) -451 Requested action aborted: local error in processing -452 Insufficient storage space in system -500 Syntax error, command unrecognized -501 Syntax error in parameters or arguments -502 Command not implemented -503 Bad sequence of commands -504 Command not implemented for that parameter -530 Not logged in -532 Need account for storing files -550 File unavailable (e.g., file not found, no access) -551 Requested action aborted. Page type unknown -552 Exceeded storage allocation -553 File name not allowed diff --git a/lib/libftpio/ftpio.3 b/lib/libftpio/ftpio.3 deleted file mode 100644 index 73a1072..0000000 --- a/lib/libftpio/ftpio.3 +++ /dev/null @@ -1,260 +0,0 @@ -.\" Copyright (c) 1996 Jordan Hubbard <jkh@FreeBSD.org> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" $FreeBSD$ -.\" -.Dd June 17, 1996 -.Dt FTPIO 3 -.Os -.Sh NAME -.Nm ftpLogin , -.Nm ftpChdir , -.Nm ftpErrno , -.Nm ftpGetModtime , -.Nm ftpGetSize , -.Nm ftpGet , -.Nm ftpPut , -.Nm ftpBinary , -.Nm ftpPassive , -.Nm ftpVerbose , -.Nm ftpGetURL , -.Nm ftpPutURL , -.Nm ftpLoginAf , -.Nm ftpGetURLAf , -.Nm ftpPutURLAf -.Nd FTPIO user library -.Sh SYNOPSIS -.In ftpio.h -.Ft FILE * -.Fn ftpLogin "char *host" "char *user" "char *passwd" "int ftp_port" "int verbose" "int *retcode" -.Ft int -.Fn ftpChdir "FILE *stream" "char *dirname" -.Ft int -.Fn ftpErrno "FILE *stream" -.Ft const char * -.Fn ftpErrString "int errno" -.Ft time_t -.Fn ftpGetModtime "FILE *stream" "char *file" -.Ft off_t -.Fn ftpGetSize "FILE *stream" "char *file" -.Ft FILE * -.Fn ftpGet "FILE *stream" "char *file" "off_t *seekto" -.Ft FILE * -.Fn ftpPut "FILE *stream" "char *file" -.Ft int -.Fn ftpAscii "FILE *stream" -.Ft int -.Fn ftpBinary "FILE *stream" -.Ft int -.Fn ftpPassive "FILE *stream" "int status" -.Ft void -.Fn ftpVerbose "FILE *stream" "int status" -.Ft FILE * -.Fn ftpGetURL "char *url" "char *user" "char *passwd" "int *retcode" -.Ft FILE * -.Fn ftpPutURL "char *url" "char *user" "char *passwd" "int *retcode" -.Ft FILE * -.Fn ftpLoginAf "char *host" "int af" "char *user" "char *passwd" "int ftp_port" "int verbose" "int *retcode" -.Ft FILE * -.Fn ftpGetURLAf "char *url" "int af" "char *user" "char *passwd" "int *retcode" -.Ft FILE * -.Fn ftpPutURLAf "char *url" "int af" "char *user" "char *passwd" "int *retcode" -.Sh DESCRIPTION -These functions implement a high-level library for managing FTP connections. -.Pp -The -.Fn ftpLogin -function attempts to log in using the supplied -.Fa user , -.Fa passwd , -.Fa ftp_port -(if passed as 0, -.Fa ftp_port -defaults to the standard ftp port of 21) and -.Fa verbose -fields. -If it is successful, a -standard stream descriptor is returned which should be passed to -subsequent FTP operations. -On failure, NULL is returned and -.Fa retcode -will have the error code returned by the foreign server. -.Pp -The -.Fn ftpChdir -function attempts to issue a server CD command to the directory named in -.Fa dir . -On success, zero is returned. -On failure, the error code from the server. -.Pp -The -.Fn ftpErrno -function returns the server failure code for the last operation (useful for -seeing more about what happened if you are familiar with FTP error codes). -The -.Fn ftpErrString -function returns a human readable version of the supplied server failure code. -.Pp -The -.Fn ftpGet -function attempts to retrieve the file named by the -.Fa file -argument (which is assumed to be relative to the FTP server's current directory, -see -.Fn ftpChdir ) -and returns a new FILE* pointer for the file or NULL on failure. -If -.Fa seekto -is non-NULL, the contents of the integer it points to will be used -as a restart point for the file, that is to say that the stream -returned will point -.Fa *seekto -bytes into the file gotten (this is handy for restarting failed -transfers efficiently). -If the seek operation fails, the value -of -.Fa *seekto -will be zero'd. -.Pp -The -.Fn ftpGetModtime -function returns the last modification time of the file named by the -.Fa file -argument. -If the file could not be opened or stat'd, 0 is returned. -.Pp -The -.Fn ftpGetSize -function returns the size in bytes of the file named by the -.Fa file -argument. -If the file could not be opened or stat'd, -1 is returned. -.Pp -The -.Fn ftpPut -function attempts to create a new file named by the -.Fa file -argument (which is assumed to be relative to the FTP server's current directory, -see -.Fn ftpChdir ) -and returns a new -.Fa stream -pointer for the file or NULL on failure. -.Pp -The -.Fn ftpAscii -function sets -.Tn ASCII -mode for the current server connection named by -.Fa stream . -.Pp -The -.Fn ftpBinary -function sets binary mode for the current server connection named by -.Fa stream . -.Pp -The -.Fn ftpPassive -function sets passive mode (for firewalls) for the current server connection -named by -.Fa stream -to boolean value -.Fa status . -.Pp -The -.Fn ftpVerbose -function sets the verbosity mode for the current server connection named by -.Fa stream -to boolean value -.Fa status . -.Pp -The -.Fn ftpGetURL -function attempts to retrieve the file named by the supplied -.Fa URL -and can be considered equivalent to the combined -.Fn ftpLogin , -.Fn ftpChdir -and -.Fn ftpGet -operations except that no server -.Fa stream -is ever returned - the connection to the server closes when -the file has been completely read. -Use the lower-level routines -if multiple gets are required as it will be far more efficient. -.Pp -The -.Fn ftpPutURL -function attempts to create the file named by the supplied -.Fa URL -and can be considered equivalent to the combined -.Fn ftpLogin , -.Fn ftpChdir -and -.Fn ftpPut -operations except that no server stream is ever returned - the connection -to the server closes when the file has been completely written. -Use the -lower-level routines if multiple puts are required as it will be far more -efficient. -.Pp -The -.Fn ftpLoginAf , -.Fn ftpGetURLAf , -.Fn ftpPutURLAf -functions are same as -.Fn ftpLogin , -.Fn ftpGetURL , -.Fn ftpPutURL -except that they are able to specify address family -.Fa af . -.Sh ENVIRONMENT -.Bl -tag -width FTP_PASSIVE_MODE -offset 3n -.It Ev FTP_TIMEOUT -Maximum time, in seconds, to wait for a response -from the peer before aborting an -.Tn FTP -connection. -.It Ev FTP_PASSIVE_MODE -If defined, forces the use of passive mode, unless equal -to ``NO'' or ``no'' in which case active mode is forced. -If defined, the setting of this variable always overrides any calls to -.Fn ftpPassive . -.El -.Sh HISTORY -Started life as Poul-Henning Kamp's ftp driver for the system installation -utility, later significantly mutated into a more general form as an -extension of stdio by Jordan Hubbard. -Also incorporates some ideas and -extensions from Jean-Marc Zucconi. -.Sh AUTHORS -.An Jordan Hubbard , -.An Poul-Henning Kamp -and -.An Jean-Marc Zucconi -.Sh BUGS -I am sure you can get this thing's internal state machine confused if -you really work at it, but so far it has proven itself pretty robust in -all my tests. diff --git a/lib/libftpio/ftpio.c b/lib/libftpio/ftpio.c deleted file mode 100644 index a5c9343..0000000 --- a/lib/libftpio/ftpio.c +++ /dev/null @@ -1,1069 +0,0 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Major Changelog: - * - * Jordan K. Hubbard - * 17 Jan 1996 - * - * Turned inside out. Now returns xfers as new file ids, not as a special - * `state' of FTP_t - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <ftpio.h> -#include <netdb.h> -#include <signal.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define SUCCESS 0 -#define FAILURE -1 - -#ifndef TRUE -#define TRUE (1) -#define FALSE (0) -#endif - -/* How to see by a given code whether or not the connection has timed out */ -#define FTP_TIMEOUT(code) (FtpTimedOut || code == FTP_TIMED_OUT) - -/* Internal routines - deal only with internal FTP_t type */ -static FTP_t ftp_new(void); -static void check_passive(FILE *fp); -static int ftp_read_method(void *n, char *buf, int nbytes); -static int ftp_write_method(void *n, const char *buf, int nbytes); -static int ftp_close_method(void *n); -static int writes(int fd, char *s); -static __inline char *get_a_line(FTP_t ftp); -static int get_a_number(FTP_t ftp, char **q); -static int botch(char *func, char *botch_state); -static int cmd(FTP_t ftp, const char *fmt, ...); -static int ftp_login_session(FTP_t ftp, char *host, int af, char *user, char *passwd, int port, int verbose); -static int ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto); -static int ftp_close(FTP_t ftp); -static int get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret); -static void ftp_timeout(int sig); -static void ftp_set_timeout(void); -static void ftp_clear_timeout(void); -static void ai_unmapped(struct addrinfo *); - - -/* Global status variable - ick */ -int FtpTimedOut; - -/* FTP happy status codes */ -#define FTP_GENERALLY_HAPPY 200 -#define FTP_ASCII_HAPPY FTP_GENERALLY_HAPPY -#define FTP_BINARY_HAPPY FTP_GENERALLY_HAPPY -#define FTP_PORT_HAPPY FTP_GENERALLY_HAPPY -#define FTP_HAPPY_COMMENT 220 -#define FTP_QUIT_HAPPY 221 -#define FTP_TRANSFER_HAPPY 226 -#define FTP_PASSIVE_HAPPY 227 -#define FTP_LPASSIVE_HAPPY 228 -#define FTP_EPASSIVE_HAPPY 229 -#define FTP_CHDIR_HAPPY 250 - -/* FTP unhappy status codes */ -#define FTP_TIMED_OUT 421 - -/* - * XXX - * gross! evil! bad! We really need an access primitive for cookie in stdio itself. - * it's too convenient a hook to bury and it's already exported through funopen as it is, so... - * XXX - */ -#define fcookie(fp) ((fp)->_cookie) - -/* Placeholder in case we want to do any pre-init stuff at some point */ -int -networkInit() -{ - return SUCCESS; /* XXX dummy function for now XXX */ -} - -/* Check a return code with some lenience for back-dated garbage that might be in the buffer */ -static int -check_code(FTP_t ftp, int var, int preferred) -{ - ftp->error = 0; - while (1) { - if (var == preferred) - return 0; - else if (var == FTP_TRANSFER_HAPPY) /* last operation succeeded */ - var = get_a_number(ftp, NULL); - else if (var == FTP_HAPPY_COMMENT) /* chit-chat */ - var = get_a_number(ftp, NULL); - else if (var == FTP_GENERALLY_HAPPY) /* general success code */ - var = get_a_number(ftp, NULL); - else { - ftp->error = var; - return 1; - } - } -} - -int -ftpAscii(FILE *fp) -{ - FTP_t ftp = fcookie(fp); - int i; - - if (!ftp->is_binary) - return SUCCESS; - i = cmd(ftp, "TYPE A"); - if (i < 0 || check_code(ftp, i, FTP_ASCII_HAPPY)) - return i; - ftp->is_binary = FALSE; - return SUCCESS; -} - -int -ftpBinary(FILE *fp) -{ - FTP_t ftp = fcookie(fp); - int i; - - if (ftp->is_binary) - return SUCCESS; - i = cmd(ftp, "TYPE I"); - if (i < 0 || check_code(ftp, i, FTP_BINARY_HAPPY)) - return i; - ftp->is_binary = TRUE; - return SUCCESS; -} -void -ftpVerbose(FILE *fp, int status) -{ - FTP_t ftp = fcookie(fp); - ftp->is_verbose = status; -} - -int -ftpChdir(FILE *fp, char *dir) -{ - int i; - FTP_t ftp = fcookie(fp); - - i = cmd(ftp, "CWD %s", dir); - if (i < 0 || check_code(ftp, i, FTP_CHDIR_HAPPY)) - return i; - return SUCCESS; -} - -int -ftpErrno(FILE *fp) -{ - FTP_t ftp = fcookie(fp); - return ftp->error; -} - -const char * -ftpErrString(int error) -{ - int k; - - if (error == -1) - return("connection in wrong state"); - if (error < 100) - /* XXX soon UNIX errnos will catch up with FTP protocol errnos */ - return strerror(error); - for (k = 0; k < ftpErrListLength; k++) - if (ftpErrList[k].num == error) - return(ftpErrList[k].string); - return("Unknown error"); -} - -off_t -ftpGetSize(FILE *fp, char *name) -{ - int i; - char p[BUFSIZ], *cp, *ep; - FTP_t ftp = fcookie(fp); - off_t size; - - check_passive(fp); - sprintf(p, "SIZE %s\r\n", name); - if (ftp->is_verbose) - fprintf(stderr, "Sending %s", p); - if (writes(ftp->fd_ctrl, p)) - return (off_t)-1; - i = get_a_number(ftp, &cp); - if (check_code(ftp, i, 213)) - return (off_t)-1; - - errno = 0; /* to check for ERANGE */ - size = (off_t)strtoq(cp, &ep, 10); - if (*ep != '\0' || errno == ERANGE) - return (off_t)-1; - return size; -} - -time_t -ftpGetModtime(FILE *fp, char *name) -{ - char p[BUFSIZ], *cp; - struct tm t; - time_t t0 = time (0); - FTP_t ftp = fcookie(fp); - int i; - - check_passive(fp); - sprintf(p, "MDTM %s\r\n", name); - if (ftp->is_verbose) - fprintf(stderr, "Sending %s", p); - if (writes(ftp->fd_ctrl, p)) - return (time_t)0; - i = get_a_number(ftp, &cp); - if (check_code(ftp, i, 213)) - return (time_t)0; - while (*cp && !isdigit(*cp)) - cp++; - if (!*cp) - return (time_t)0; - t0 = localtime (&t0)->tm_gmtoff; - sscanf(cp, "%04d%02d%02d%02d%02d%02d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec); - t.tm_mon--; - t.tm_year -= 1900; - t.tm_isdst=-1; - t.tm_gmtoff = 0; - t0 += mktime (&t); - return t0; -} - -FILE * -ftpGet(FILE *fp, char *file, off_t *seekto) -{ - FILE *fp2; - FTP_t ftp = fcookie(fp); - - check_passive(fp); - if (ftpBinary(fp) != SUCCESS) - return NULL; - - if (ftp_file_op(ftp, "RETR", file, &fp2, "r", seekto) == SUCCESS) - return fp2; - return NULL; -} - -/* Returns a standard FILE pointer type representing an open control connection */ -FILE * -ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode) -{ -#ifdef INET6 - return ftpLoginAf(host, AF_UNSPEC, user, passwd, port, verbose, retcode); -#else - return ftpLoginAf(host, AF_INET, user, passwd, port, verbose, retcode); -#endif -} - -FILE * -ftpLoginAf(char *host, int af, char *user, char *passwd, int port, int verbose, int *retcode) -{ - FTP_t n; - FILE *fp; - - if (retcode) - *retcode = 0; - if (networkInit() != SUCCESS) - return NULL; - - n = ftp_new(); - fp = NULL; - if (n && ftp_login_session(n, host, af, user, passwd, port, verbose) == SUCCESS) { - fp = funopen(n, ftp_read_method, ftp_write_method, NULL, ftp_close_method); /* BSD 4.4 function! */ - } - if (retcode) { - if (!n) - *retcode = (FtpTimedOut ? FTP_TIMED_OUT : -1); - /* Poor attempt at mapping real errnos to FTP error codes */ - else switch(n->error) { - case EADDRNOTAVAIL: - *retcode = FTP_TIMED_OUT; /* Actually no such host, but we have no way of saying that. :-( */ - break; - - case ETIMEDOUT: - *retcode = FTP_TIMED_OUT; - break; - - default: - *retcode = n->error; - break; - } - } - return fp; -} - -FILE * -ftpPut(FILE *fp, char *file) -{ - FILE *fp2; - FTP_t ftp = fcookie(fp); - - check_passive(fp); - if (ftp_file_op(ftp, "STOR", file, &fp2, "w", NULL) == SUCCESS) - return fp2; - return NULL; -} - -int -ftpPassive(FILE *fp, int st) -{ - FTP_t ftp = fcookie(fp); - - ftp->is_passive = !!st; /* normalize "st" to zero or one */ - return SUCCESS; -} - -FILE * -ftpGetURL(char *url, char *user, char *passwd, int *retcode) -{ -#ifdef INET6 - return ftpGetURLAf(url, AF_UNSPEC, user, passwd, retcode); -#else - return ftpGetURLAf(url, AF_INET, user, passwd, retcode); -#endif -} - -FILE * -ftpGetURLAf(char *url, int af, char *user, char *passwd, int *retcode) -{ - char host[255], name[255]; - int port; - FILE *fp2; - static FILE *fp = NULL; - static char *prev_host; - - if (retcode) - *retcode = 0; - if (get_url_info(url, host, &port, name) == SUCCESS) { - if (fp && prev_host) { - if (!strcmp(prev_host, host)) { - /* Try to use cached connection */ - fp2 = ftpGet(fp, name, NULL); - if (!fp2) { - /* Connection timed out or was no longer valid */ - fclose(fp); - free(prev_host); - prev_host = NULL; - } - else - return fp2; - } - else { - /* It's a different host now, flush old */ - fclose(fp); - free(prev_host); - prev_host = NULL; - } - } - fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode); - if (fp) { - fp2 = ftpGet(fp, name, NULL); - if (!fp2) { - /* Connection timed out or was no longer valid */ - if (retcode) - *retcode = ftpErrno(fp); - fclose(fp); - fp = NULL; - } - else - prev_host = strdup(host); - return fp2; - } - } - return NULL; -} - -FILE * -ftpPutURL(char *url, char *user, char *passwd, int *retcode) -{ -#ifdef INET6 - return ftpPutURLAf(url, AF_UNSPEC, user, passwd, retcode); -#else - return ftpPutURLAf(url, AF_INET, user, passwd, retcode); -#endif - -} - -FILE * -ftpPutURLAf(char *url, int af, char *user, char *passwd, int *retcode) -{ - char host[255], name[255]; - int port; - static FILE *fp = NULL; - FILE *fp2; - - if (retcode) - *retcode = 0; - if (fp) { /* Close previous managed connection */ - fclose(fp); - fp = NULL; - } - if (get_url_info(url, host, &port, name) == SUCCESS) { - fp = ftpLoginAf(host, af, user, passwd, port, 0, retcode); - if (fp) { - fp2 = ftpPut(fp, name); - if (!fp2) { - if (retcode) - *retcode = ftpErrno(fp); - fclose(fp); - fp = NULL; - } - return fp2; - } - } - return NULL; -} - -/* Internal workhorse function for dissecting URLs. Takes a URL as the first argument and returns the - result of such disection in the host, user, passwd, port and name variables. */ -static int -get_url_info(char *url_in, char *host_ret, int *port_ret, char *name_ret) -{ - char *name, *host, *cp, url[BUFSIZ]; - int port; - - name = host = NULL; - /* XXX add http:// here or somewhere reasonable at some point XXX */ - if (strncmp("ftp://", url_in, 6) != 0) - return FAILURE; - /* We like to stomp a lot on the URL string in dissecting it, so copy it first */ - strncpy(url, url_in, BUFSIZ); - host = url + 6; - if ((cp = index(host, ':')) != NULL) { - *(cp++) = '\0'; - port = strtol(cp, 0, 0); - } - else - port = 0; /* use default */ - if (port_ret) - *port_ret = port; - - if ((name = index(cp ? cp : host, '/')) != NULL) - *(name++) = '\0'; - if (host_ret) - strcpy(host_ret, host); - if (name && name_ret) - strcpy(name_ret, name); - return SUCCESS; -} - -static FTP_t -ftp_new(void) -{ - FTP_t ftp; - - ftp = (FTP_t)malloc(sizeof *ftp); - if (!ftp) - return NULL; - memset(ftp, 0, sizeof *ftp); - ftp->fd_ctrl = -1; - ftp->con_state = init; - ftp->is_binary = FALSE; - ftp->is_passive = FALSE; - ftp->is_verbose = FALSE; - ftp->error = 0; - return ftp; -} - -static int -ftp_read_method(void *vp, char *buf, int nbytes) -{ - int i, fd; - FTP_t n = (FTP_t)vp; - - fd = n->fd_ctrl; - i = (fd >= 0) ? read(fd, buf, nbytes) : EOF; - return i; -} - -static int -ftp_write_method(void *vp, const char *buf, int nbytes) -{ - int i, fd; - FTP_t n = (FTP_t)vp; - - fd = n->fd_ctrl; - i = (fd >= 0) ? write(fd, buf, nbytes) : EOF; - return i; -} - -static int -ftp_close_method(void *n) -{ - int i; - - i = ftp_close((FTP_t)n); - free(n); - return i; -} - -/* - * This function checks whether the FTP_PASSIVE_MODE environment - * variable is set, and, if so, enforces the desired mode. - */ -static void -check_passive(FILE *fp) -{ - const char *cp = getenv("FTP_PASSIVE_MODE"); - - if (cp != NULL) - ftpPassive(fp, strncasecmp(cp, "no", 2)); -} - -static void -ftp_timeout(int sig) -{ - FtpTimedOut = TRUE; - /* Debug("ftp_pkg: ftp_timeout called - operation timed out"); */ -} - -static void -ftp_set_timeout(void) -{ - struct sigaction new; - char *cp; - int ival; - - FtpTimedOut = FALSE; - sigemptyset(&new.sa_mask); - new.sa_flags = 0; - new.sa_handler = ftp_timeout; - sigaction(SIGALRM, &new, NULL); - cp = getenv("FTP_TIMEOUT"); - if (!cp || !(ival = atoi(cp))) - ival = 120; - alarm(ival); -} - -static void -ftp_clear_timeout(void) -{ - struct sigaction new; - - alarm(0); - sigemptyset(&new.sa_mask); - new.sa_flags = 0; - new.sa_handler = SIG_DFL; - sigaction(SIGALRM, &new, NULL); -} - -static int -writes(int fd, char *s) -{ - int n, i = strlen(s); - - ftp_set_timeout(); - n = write(fd, s, i); - ftp_clear_timeout(); - if (FtpTimedOut || i != n) - return TRUE; - return FALSE; -} - -static __inline char * -get_a_line(FTP_t ftp) -{ - static char buf[BUFSIZ]; - int i,j; - - /* Debug("ftp_pkg: trying to read a line from %d", ftp->fd_ctrl); */ - for(i = 0; i < BUFSIZ;) { - ftp_set_timeout(); - j = read(ftp->fd_ctrl, buf + i, 1); - ftp_clear_timeout(); - if (FtpTimedOut || j != 1) - return NULL; - if (buf[i] == '\r' || buf[i] == '\n') { - if (!i) - continue; - buf[i] = '\0'; - if (ftp->is_verbose == TRUE) - fprintf(stderr, "%s\n",buf+4); - return buf; - } - i++; - } - /* Debug("ftp_pkg: read string \"%s\" from %d", buf, ftp->fd_ctrl); */ - return buf; -} - -static int -get_a_number(FTP_t ftp, char **q) -{ - char *p; - int i = -1, j; - - while(1) { - p = get_a_line(ftp); - if (!p) { - ftp_close(ftp); - if (FtpTimedOut) - return FTP_TIMED_OUT; - return FAILURE; - } - if (!(isdigit(p[0]) && isdigit(p[1]) && isdigit(p[2]))) - continue; - if (i == -1 && p[3] == '-') { - i = strtol(p, 0, 0); - continue; - } - if (p[3] != ' ' && p[3] != '\t') - continue; - j = strtol(p, 0, 0); - if (i == -1) { - if (q) *q = p+4; - /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */ - return j; - } else if (j == i) { - if (q) *q = p+4; - /* Debug("ftp_pkg: read reply %d from server (%s)", j, p); */ - return j; - } - } -} - -static int -ftp_close(FTP_t ftp) -{ - int i, rcode; - - rcode = FAILURE; - if (ftp->con_state == isopen) { - ftp->con_state = quit; - /* If last operation timed out, don't try to quit - just close */ - if (ftp->error != FTP_TIMED_OUT) - i = cmd(ftp, "QUIT"); - else - i = FTP_QUIT_HAPPY; - if (!check_code(ftp, i, FTP_QUIT_HAPPY)) - rcode = SUCCESS; - close(ftp->fd_ctrl); - ftp->fd_ctrl = -1; - } - else if (ftp->con_state == quit) - rcode = SUCCESS; - return rcode; -} - -static int -botch(char *func, char *botch_state) -{ - /* Debug("ftp_pkg: botch: %s(%s)", func, botch_state); */ - return FAILURE; -} - -static int -cmd(FTP_t ftp, const char *fmt, ...) -{ - char p[BUFSIZ]; - int i; - - va_list ap; - va_start(ap, fmt); - (void)vsnprintf(p, sizeof p, fmt, ap); - va_end(ap); - - if (ftp->con_state == init) - return botch("cmd", "open"); - - strcat(p, "\r\n"); - if (ftp->is_verbose) - fprintf(stderr, "Sending: %s", p); - if (writes(ftp->fd_ctrl, p)) { - if (FtpTimedOut) - return FTP_TIMED_OUT; - return FAILURE; - } - while ((i = get_a_number(ftp, NULL)) == FTP_HAPPY_COMMENT); - return i; -} - -static int -ftp_login_session(FTP_t ftp, char *host, int af, - char *user, char *passwd, int port, int verbose) -{ - char pbuf[10]; - struct addrinfo hints, *res, *res0; - int err; - int s; - int i; - - if (networkInit() != SUCCESS) - return FAILURE; - - if (ftp->con_state != init) { - ftp_close(ftp); - ftp->error = -1; - return FAILURE; - } - - if (!user) - user = "ftp"; - - if (!passwd) - passwd = "setup@"; - - if (!port) - port = 21; - - snprintf(pbuf, sizeof(pbuf), "%d", port); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = af; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - err = getaddrinfo(host, pbuf, &hints, &res0); - if (err) { - ftp->error = 0; - return FAILURE; - } - - s = -1; - for (res = res0; res; res = res->ai_next) { - ai_unmapped(res); - ftp->addrtype = res->ai_family; - - if ((s = socket(res->ai_family, res->ai_socktype, - res->ai_protocol)) < 0) - continue; - - if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { - (void)close(s); - s = -1; - continue; - } - - break; - } - freeaddrinfo(res0); - if (s < 0) { - ftp->error = errno; - return FAILURE; - } - - ftp->fd_ctrl = s; - ftp->con_state = isopen; - ftp->is_verbose = verbose; - - i = cmd(ftp, "USER %s", user); - if (i >= 300 && i < 400) - i = cmd(ftp, "PASS %s", passwd); - if (i >= 299 || i < 0) { - ftp_close(ftp); - if (i > 0) - ftp->error = i; - return FAILURE; - } - return SUCCESS; -} - -static int -ftp_file_op(FTP_t ftp, char *operation, char *file, FILE **fp, char *mode, off_t *seekto) -{ - socklen_t sinlen; - int i,l,s; - char *q; - unsigned char addr[64]; - union sockaddr_cmn { - struct sockaddr_in sin4; - struct sockaddr_in6 sin6; - } sin; - char *cmdstr; - - if (!fp) - return FAILURE; - *fp = NULL; - - if (ftp->con_state != isopen) - return botch("ftp_file_op", "open"); - - if ((s = socket(ftp->addrtype, SOCK_STREAM, 0)) < 0) { - ftp->error = errno; - return FAILURE; - } - - if (ftp->is_passive) { - if (ftp->addrtype == AF_INET) { - if (ftp->is_verbose) - fprintf(stderr, "Sending PASV\n"); - if (writes(ftp->fd_ctrl, "PASV\r\n")) { - ftp_close(ftp); - if (FtpTimedOut) - ftp->error = FTP_TIMED_OUT; - return FTP_TIMED_OUT; - } - i = get_a_number(ftp, &q); - if (check_code(ftp, i, FTP_PASSIVE_HAPPY)) { - ftp_close(ftp); - return i; - } - cmdstr = "PASV"; - } else { - if (ftp->is_verbose) - fprintf(stderr, "Sending EPSV\n"); - if (writes(ftp->fd_ctrl, "EPSV\r\n")) { - ftp_close(ftp); - if (FtpTimedOut) - ftp->error = FTP_TIMED_OUT; - return FTP_TIMED_OUT; - } - i = get_a_number(ftp, &q); - if (check_code(ftp, i, FTP_EPASSIVE_HAPPY)) { - if (ftp->is_verbose) - fprintf(stderr, "Sending LPSV\n"); - if (writes(ftp->fd_ctrl, "LPSV\r\n")) { - ftp_close(ftp); - if (FtpTimedOut) - ftp->error = FTP_TIMED_OUT; - return FTP_TIMED_OUT; - } - i = get_a_number(ftp, &q); - if (check_code(ftp, i, FTP_LPASSIVE_HAPPY)) { - ftp_close(ftp); - return i; - } - cmdstr = "LPSV"; - } else - cmdstr = "EPSV"; - } - if (strcmp(cmdstr, "PASV") == 0 || strcmp(cmdstr, "LPSV") == 0) { - while (*q && !isdigit(*q)) - q++; - if (!*q) { - ftp_close(ftp); - return FAILURE; - } - q--; - l = (ftp->addrtype == AF_INET ? 6 : 21); - for (i = 0; i < l; i++) { - q++; - addr[i] = strtol(q, &q, 10); - } - - sin.sin4.sin_family = ftp->addrtype; - if (ftp->addrtype == AF_INET6) { - sin.sin6.sin6_len = sizeof(struct sockaddr_in6); - bcopy(addr + 2, (char *)&sin.sin6.sin6_addr, 16); - bcopy(addr + 19, (char *)&sin.sin6.sin6_port, 2); - } else { - sin.sin4.sin_len = sizeof(struct sockaddr_in); - bcopy(addr, (char *)&sin.sin4.sin_addr, 4); - bcopy(addr + 4, (char *)&sin.sin4.sin_port, 2); - } - } else if (strcmp(cmdstr, "EPSV") == 0) { - int port; - while (*q && *q != '(') /* ) */ - q++; - if (!*q) { - ftp_close(ftp); - return FAILURE; - } - q++; - if (sscanf(q, "%c%c%c%d%c", &addr[0], &addr[1], &addr[2], - &port, &addr[3]) != 5 - || addr[0] != addr[1] || addr[0] != addr[2] || addr[0] != addr[3]) { - ftp_close(ftp); - return FAILURE; - } - sinlen = sizeof(sin); - if (getpeername(ftp->fd_ctrl, (struct sockaddr *)&sin, &sinlen) < 0) { - ftp_close(ftp); - return FAILURE; - } - switch (sin.sin4.sin_family) { - case AF_INET: - sin.sin4.sin_port = htons(port); - break; - case AF_INET6: - sin.sin6.sin6_port = htons(port); - break; - default: - ftp_close(ftp); - return FAILURE; - } - } - - if (connect(s, (struct sockaddr *)&sin, sin.sin4.sin_len) < 0) { - (void)close(s); - return FAILURE; - } - - if (seekto && *seekto) { - i = cmd(ftp, "REST %d", *seekto); - if (i < 0 || FTP_TIMEOUT(i)) { - close(s); - ftp->error = i; - *seekto = (off_t)0; - return i; - } - } - i = cmd(ftp, "%s %s", operation, file); - if (i < 0 || i > 299) { - close(s); - ftp->error = i; - return i; - } - *fp = fdopen(s, mode); - } - else { - int fd,portrange; - -#ifdef IPV6_PORTRANGE - if (ftp->addrtype == AF_INET6) { - portrange = IPV6_PORTRANGE_HIGH; - if (setsockopt(s, IPPROTO_IPV6, IPV6_PORTRANGE, (char *) - &portrange, sizeof(portrange)) < 0) { - close(s); - return FAILURE; - } - } -#endif -#ifdef IP_PORTRANGE - if (ftp->addrtype == AF_INET) { - portrange = IP_PORTRANGE_HIGH; - if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char *) - &portrange, sizeof(portrange)) < 0) { - close(s); - return FAILURE; - } - } -#endif - - sinlen = sizeof sin; - getsockname(ftp->fd_ctrl, (struct sockaddr *)&sin, &sinlen); - sin.sin4.sin_port = 0; - i = ((struct sockaddr *)&sin)->sa_len; - if (bind(s, (struct sockaddr *)&sin, i) < 0) { - close(s); - return FAILURE; - } - sinlen = sizeof sin; - getsockname(s, (struct sockaddr *)&sin, &sinlen); - if (listen(s, 1) < 0) { - close(s); - return FAILURE; - } - if (sin.sin4.sin_family == AF_INET) { - u_long a; - a = ntohl(sin.sin4.sin_addr.s_addr); - i = cmd(ftp, "PORT %d,%d,%d,%d,%d,%d", - (a >> 24) & 0xff, - (a >> 16) & 0xff, - (a >> 8) & 0xff, - a & 0xff, - (ntohs(sin.sin4.sin_port) >> 8) & 0xff, - ntohs(sin.sin4.sin_port) & 0xff); - if (check_code(ftp, i, FTP_PORT_HAPPY)) { - close(s); - return i; - } - } else { -#define UC(b) (((int)b)&0xff) - char *a; - char hname[INET6_ADDRSTRLEN]; - - sin.sin6.sin6_scope_id = 0; - if (getnameinfo((struct sockaddr *)&sin, sin.sin6.sin6_len, - hname, sizeof(hname), - NULL, 0, NI_NUMERICHOST) != 0) { - goto try_lprt; - } - i = cmd(ftp, "EPRT |%d|%s|%d|", 2, hname, - htons(sin.sin6.sin6_port)); - if (check_code(ftp, i, FTP_PORT_HAPPY)) { -try_lprt: - a = (char *)&sin.sin6.sin6_addr; - i = cmd(ftp, -"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", - 6, 16, - UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), - UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), - UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), - UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), - 2, - (ntohs(sin.sin4.sin_port) >> 8) & 0xff, - ntohs(sin.sin4.sin_port) & 0xff); - if (check_code(ftp, i, FTP_PORT_HAPPY)) { - close(s); - return i; - } - } - } - if (seekto && *seekto) { - i = cmd(ftp, "REST %d", *seekto); - if (i < 0 || FTP_TIMEOUT(i)) { - close(s); - ftp->error = i; - return i; - } - else if (i != 350) - *seekto = (off_t)0; - } - i = cmd(ftp, "%s %s", operation, file); - if (i < 0 || i > 299) { - close(s); - ftp->error = i; - return FAILURE; - } - fd = accept(s, 0, 0); - if (fd < 0) { - close(s); - ftp->error = 401; - return FAILURE; - } - close(s); - *fp = fdopen(fd, mode); - } - if (*fp) - return SUCCESS; - else - return FAILURE; -} - -static void -ai_unmapped(struct addrinfo *ai) -{ - struct sockaddr_in6 *sin6; - struct sockaddr_in sin; - - if (ai->ai_family != AF_INET6) - return; - if (ai->ai_addrlen != sizeof(struct sockaddr_in6) || - sizeof(sin) > ai->ai_addrlen) - return; - sin6 = (struct sockaddr_in6 *)ai->ai_addr; - if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - return; - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(struct sockaddr_in); - memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12], - sizeof(sin.sin_addr)); - sin.sin_port = sin6->sin6_port; - - ai->ai_family = AF_INET; - memcpy(ai->ai_addr, &sin, sin.sin_len); - ai->ai_addrlen = sin.sin_len; -} diff --git a/lib/libftpio/ftpio.h b/lib/libftpio/ftpio.h deleted file mode 100644 index 879abea..0000000 --- a/lib/libftpio/ftpio.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _FTP_H_INCLUDE -#define _FTP_H_INCLUDE - -#include <sys/types.h> -#include <sys/cdefs.h> -#include <stdio.h> -#include <time.h> - -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * - * Major Changelog: - * - * Jordan K. Hubbard - * 17 Jan 1996 - * - * Turned inside out. Now returns xfers as new file ids, not as a special - * `state' of FTP_t - * - * $FreeBSD$ - */ - -/* Internal housekeeping data structure for FTP sessions */ -typedef struct { - enum { init, isopen, quit } con_state; - int fd_ctrl; - int addrtype; - char *host; - char *file; - int error; - int is_binary; - int is_passive; - int is_verbose; -} *FTP_t; - -/* Structure we use to match FTP error codes with readable strings */ -struct ftperr { - const int num; - const char *string; -}; - -__BEGIN_DECLS -extern struct ftperr ftpErrList[]; -extern int const ftpErrListLength; - -/* Exported routines - deal only with FILE* type */ -extern FILE *ftpLogin(char *host, char *user, char *passwd, int port, int verbose, int *retcode); -extern int ftpChdir(FILE *fp, char *dir); -extern int ftpErrno(FILE *fp); -extern off_t ftpGetSize(FILE *fp, char *file); -extern FILE *ftpGet(FILE *fp, char *file, off_t *seekto); -extern FILE *ftpPut(FILE *fp, char *file); -extern int ftpAscii(FILE *fp); -extern int ftpBinary(FILE *fp); -extern int ftpPassive(FILE *fp, int status); -extern void ftpVerbose(FILE *fp, int status); -extern FILE *ftpGetURL(char *url, char *user, char *passwd, int *retcode); -extern FILE *ftpPutURL(char *url, char *user, char *passwd, int *retcode); -extern time_t ftpGetModtime(FILE *fp, char *s); -extern const char *ftpErrString(int error); -extern FILE *ftpLoginAf(char *host, int af, char *user, char *passwd, int port, int verbose, int *retcode); -extern FILE *ftpGetURLAf(char *url, int af, char *user, char *passwd, int *retcode); -extern FILE *ftpPutURLAf(char *url, int af, char *user, char *passwd, int *retcode); -__END_DECLS - -#endif /* _FTP_H_INCLUDE */ |