⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftp.c

📁 linux 安装程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * ftp.c - ftp code * * Erik Troan <ewt@redhat.com> * Matt Wilson <msw@redhat.com> * Jeremy Katz <katzj@redhat.com> * David Cantrell <dcantrell@redhat.com> * * Copyright 1997 - 2006 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * General Public License. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define HAVE_ALLOCA_H 1#define HAVE_NETINET_IN_SYSTM_H 1#define HAVE_SYS_SOCKET_H 1#define USE_ALT_DNS 1#if HAVE_ALLOCA_H# include <alloca.h>#endif#if HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif#if HAVE_NETINET_IN_SYSTM_H# include <sys/types.h># include <netinet/in_systm.h>#endif#if ! HAVE_HERRNOextern int h_errno;#endif#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <pwd.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <netinet/in.h>#include <netinet/ip.h>#include <arpa/inet.h>#define TIMEOUT_SECS 60#define BUFFER_SIZE 4096#ifndef IPPORT_FTP# define IPPORT_FTP 21#endif#if defined(USE_ALT_DNS) && USE_ALT_DNS #include "../isys/dns.h"#endif#include "ftp.h"#include "log.h"#include "net.h"static int ftpCheckResponse(int sock, char ** str);static int ftpCommand(int sock, char * command, ...);static int getHostAddress(const char * host, void * address, int family);static int ftpCheckResponse(int sock, char ** str) {    static char buf[BUFFER_SIZE + 1];    int bufLength = 0;     fd_set emptySet, readSet;    char * chptr, * start;    struct timeval timeout;    int bytesRead, rc = 0;    int doesContinue = 1;    char errorCode[4];     errorCode[0] = '\0';        do {        FD_ZERO(&emptySet);        FD_ZERO(&readSet);        FD_SET(sock, &readSet);        timeout.tv_sec = TIMEOUT_SECS;        timeout.tv_usec = 0;            rc = select(sock + 1, &readSet, &emptySet, &emptySet, &timeout);        if (rc < 1) {            if (rc==0)                 return FTPERR_BAD_SERVER_RESPONSE;            else                rc = FTPERR_UNKNOWN;        } else {            rc = 0;        }        bytesRead = read(sock, buf + bufLength, sizeof(buf) - bufLength - 1);        bufLength += bytesRead;        buf[bufLength] = '\0';        /* divide the response into lines, checking each one to see if            we are finished or need to continue */        start = chptr = buf;        do {            while (*chptr != '\n' && *chptr) chptr++;            if (*chptr == '\n') {                *chptr = '\0';                if (*(chptr - 1) == '\r') *(chptr - 1) = '\0';                if (str) *str = start;                if (errorCode[0]) {                    if (!strncmp(start, errorCode, 3) && start[3] == ' ')                        doesContinue = 0;                } else {                    strncpy(errorCode, start, 3);                    errorCode[3] = '\0';                    if (start[3] != '-') {                        doesContinue = 0;                    }                 }                start = chptr + 1;                chptr++;            } else {                chptr++;            }        } while (*chptr);        if (doesContinue && chptr > start) {            memcpy(buf, start, chptr - start - 1);            bufLength = chptr - start - 1;        } else {            bufLength = 0;        }    } while (doesContinue && !rc);    if (*errorCode == '4' || *errorCode == '5') {        if (!strncmp(errorCode, "421", 3)) {            return FTPERR_TOO_MANY_CONNECTIONS;        } else if (!strncmp(errorCode, "550", 3)) {            return FTPERR_FILE_NOT_FOUND;        }        return FTPERR_BAD_SERVER_RESPONSE;    }    if (rc) return rc;    return 0;}int ftpCommand(int sock, char * command, ...) {    va_list ap;    int len;    char * s;    char * buf;    int rc;    va_start(ap, command);    len = strlen(command) + 2;    s = va_arg(ap, char *);    while (s) {        len += strlen(s) + 1;        s = va_arg(ap, char *);    }    va_end(ap);    buf = alloca(len + 1);    va_start(ap, command);    strcpy(buf, command);    strcat(buf, " ");    s = va_arg(ap, char *);    while (s) {        strcat(buf, s);        strcat(buf, " ");        s = va_arg(ap, char *);    }    va_end(ap);    buf[len - 2] = '\r';    buf[len - 1] = '\n';    buf[len] = '\0';         if (write(sock, buf, len) != len) {        return FTPERR_SERVER_IO_ERROR;    }    if ((rc = ftpCheckResponse(sock, NULL)))        return rc;    return 0;}static int getHostAddress(const char * host, void * address, int family) {    char *hostname, *port;    splitHostname((char *) host, &hostname, &port);    if (family == AF_INET) {        if (isdigit(host[0])) {            if (inet_pton(AF_INET, hostname, (struct in_addr *)address) >= 1) {                return 0;            } else {                return FTPERR_BAD_HOST_ADDR;            }        } else {            if (mygethostbyname(hostname, (struct in_addr *)address, AF_INET)) {                errno = h_errno;                return FTPERR_BAD_HOSTNAME;            } else {                return 0;            }        }    } else if (family == AF_INET6) {        if (strchr(hostname, ':')) {            if (inet_pton(AF_INET6, hostname, (struct in_addr6 *)address) >= 1) {                return 0;            } else                return FTPERR_BAD_HOST_ADDR;        } else {            /* FIXME: implement me */            logMessage(ERROR, "we don't have reverse DNS for IPv6 yet");            return FTPERR_BAD_HOSTNAME;        }    } else {        return FTPERR_UNSUPPORTED_FAMILY;    }}int ftpOpen(char *host, int family, char *name, char *password,            char *proxy, int port) {    static int sock;    struct in_addr addr;    struct in6_addr addr6;    struct sockaddr_in destPort;    struct sockaddr_in6 destPort6;    struct passwd * pw;    char * buf;    int rc = 0;    if (port < 0) port = IPPORT_FTP;    if (!name)        name = "anonymous";    if (!password) {        password = "root@";        if (getuid()) {            pw = getpwuid(getuid());            if (pw) {                password = alloca(strlen(pw->pw_name) + 2);                strcpy(password, pw->pw_name);                strcat(password, "@");            }        }    }    if (proxy) {        if (asprintf(&buf, "%s@%s", name, host) != -1)            name = buf;        host = proxy;    }    if (family == AF_INET)        rc = getHostAddress(host, &addr, AF_INET);    else if (family == AF_INET6)        rc = getHostAddress(host, &addr6, AF_INET6);    if (rc)        return rc;    sock = socket(family, SOCK_STREAM, IPPROTO_IP);    if (sock < 0) {        return FTPERR_FAILED_CONNECT;    }    if (family == AF_INET) {        destPort.sin_family = family;        destPort.sin_port = htons(port);        destPort.sin_addr = addr;        if (connect(sock, (struct sockaddr *) &destPort, sizeof(destPort))) {            close(sock);            return FTPERR_FAILED_CONNECT;        }    } else if (family == AF_INET6) {        destPort6.sin6_family = family;        destPort6.sin6_port = htons(port);        destPort6.sin6_addr = addr6;        if (connect(sock, (struct sockaddr *) &destPort6, sizeof(destPort6))) {            close(sock);            return FTPERR_FAILED_CONNECT;        }    }    /* ftpCheckResponse() assumes the socket is nonblocking */    if (fcntl(sock, F_SETFL, O_NONBLOCK)) {        close(sock);        return FTPERR_FAILED_CONNECT;    }    if ((rc = ftpCheckResponse(sock, NULL))) {        return rc;         }    if ((rc = ftpCommand(sock, "USER", name, NULL))) {        close(sock);        return rc;    }    if ((rc = ftpCommand(sock, "PASS", password, NULL))) {        close(sock);        return rc;    }    if ((rc = ftpCommand(sock, "TYPE", "I", NULL))) {        close(sock);        return rc;    }    return sock;}/* * FTP specification: * RFC 959  FILE TRANSFER PROTOCOL (FTP) * RFC 2428 FTP Extensions for IPv6 and NATs */int ftpGetFileDesc(int sock, struct in6_addr host, int family,                   char * remotename) {    int dataSocket;    struct sockaddr_in dataAddress;    struct sockaddr_in6 dataAddress6;    int i, j;    char * passReply;    char * chptr;    char * retrCommand;    int rc;    if (family == AF_INET) {        if (write(sock, "PASV\r\n", 6) != 6) {            return FTPERR_SERVER_IO_ERROR;        }    } else if (family == AF_INET6) {        if (write(sock, "EPSV\r\n", 6) != 6) {            return FTPERR_SERVER_IO_ERROR;        }    }    if ((rc = ftpCheckResponse(sock, &passReply))) {        return FTPERR_PASSIVE_ERROR;    }    /* get IP address and port number from server response */    if (family == AF_INET) {        /* we have a PASV response of the form:         * 227 Entering Passive Mode (209,132,176,30,57,229)         * where 209.132.176.30 is the IP, and 57 & 229 are the ports         */        chptr = passReply;        while (*chptr && *chptr != '(') chptr++;        if (*chptr != '(') {            return FTPERR_PASSIVE_ERROR;        }        chptr++;        passReply = chptr;        while (*chptr && *chptr != ')') chptr++;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -