📄 ftplib.c
字号:
if (dig == 1) /* char 1 is code type */ codeType = c - '0'; if (dig <= 3) /* chars 1-3 are code */ { if (!isdigit ((int)c)) code = -1; else if (code != -1) code = code * 10 + (c - '0'); } if (dig == 4) /* char 4 is continuation marker */ continuation = (c == '-'); if ((c != '\r') && (((ftplDebug & FTPL_DEBUG_INCOMING) && (dig > 4)) || (ftplDebug && (codeType == FTP_ERROR))) ) { write (STD_ERR, &c, 1); } } /* terminate the reply string */ if (replyString != NULL) replyString[stringIndex] = c; /* print newline if we've been printing this reply */ if ((ftplDebug & FTPL_DEBUG_INCOMING) || ((codeType == FTP_ERROR) && ftplDebug)) printErr ("\n"); /* save the original reply code */ if (origCode == 0) origCode = code; } /* while not eof and not last line of reply */ while (!eof && !((dig >= 3) && (code == origCode) && !continuation)); /* set status to entire reply code */ errno = (M_ftpLib | origCode); /* return error if unexpected eof encountered */ if (eof & !expecteof) { FTPLDEBUG ("ftpReplyGet: error - experienced eof - errno:0x%08x\n", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); return (ERROR); } else return (origCode); /* Return the complete code */ }/********************************************************************************* ftpHookup - get a control connection to the FTP server on a specified host** This routine establishes a control connection to the FTP server on the* specified host. This is the first step in interacting with a remote FTP* server at the lowest level. (For a higher-level interaction with a remote* FTP server, see the manual entry for ftpXfer().)** RETURNS:* The file descriptor of the control socket, or ERROR if the Internet* address or the host name is invalid, if a socket could not be created, or* if a connection could not be made.** SEE ALSO: ftpLogin(), ftpXfer()*/int ftpHookup ( char *host /* server host name or inet address */ ) { FAST int ctrlSock; FAST int inetAddr; SOCKADDR_IN ctrlAddr; if (((inetAddr = (int) inet_addr (host)) == ERROR) && ((inetAddr = hostGetByName (host)) == ERROR)) { return (ERROR); } /* make our control socket */ ctrlSock = socket (AF_INET, SOCK_STREAM, 0); if (ctrlSock < 0) { FTPLDEBUG ("ftpHookup: error - failure to get socket. errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, errno,1,2,3,4,5); return (ERROR); } /* bind a name with no inet address and let system pick port; * this is just so we can find our socket address later */ ctrlAddr.sin_family = AF_INET; ctrlAddr.sin_addr.s_addr = INADDR_ANY; ctrlAddr.sin_port = htons (0); if (bind (ctrlSock, (struct sockaddr *)&ctrlAddr, sizeof (ctrlAddr)) < 0) { FTPLDEBUG ("ftpHookup: error - failure to bind socket. errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, errno,1,2,3,4,5); close (ctrlSock); return (ERROR); } /* connect to other side */ ctrlAddr.sin_addr.s_addr = inetAddr; ctrlAddr.sin_port = htons (FTP_PORT); if (connect (ctrlSock, (struct sockaddr *)&ctrlAddr, sizeof (ctrlAddr)) < 0) { FTPLDEBUG ("ftpHookup: error - failure to connect socket. errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, errno,1,2,3,4,5); close (ctrlSock); return (ERROR); } ftpReplyGet (ctrlSock, FALSE); /* read startup message from server */ return (ctrlSock); }/********************************************************************************* ftpLogin - log in to a remote FTP server** This routine logs in to a remote server with the specified user name,* password, and account name, as required by the specific remote host. This* is typically the next step after calling ftpHookup() in interacting with a* remote FTP server at the lowest level. (For a higher-level interaction* with a remote FTP server, see the manual entry for ftpXfer()).** RETURNS:* OK, or ERROR if the routine is unable to log in.** SEE ALSO: ftpHookup(), ftpXfer()*/STATUS ftpLogin ( FAST int ctrlSock, /* fd of login control socket */ char *user, /* user name for host login */ char *passwd, /* password for host login */ char *account /* account for host login */ ) { FAST int n; n = ftpCommand (ctrlSock, "USER %s", (int)user, 0, 0, 0, 0, 0); if (n == FTP_CONTINUE) n = ftpCommand (ctrlSock, "PASS %s", (int)passwd, 0, 0, 0, 0, 0); if (n == FTP_CONTINUE) n = ftpCommand (ctrlSock, "ACCT %s", (int)account, 0, 0, 0, 0, 0); if (n != FTP_COMPLETE) { FTPLDEBUG ("ftpLogin: error - failure to get complete login. errno:0x%08x\n",\ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); return (ERROR); } return (OK); }/********************************************************************************* ftpDataConnInitPassiveMode - initialize an FTP data connection using PASV mode** This routine sets up the client side of a data connection for the* specified control connection. It issues a PASV command and attempts to connect* to the host-specified port. If the host responds that it can not process the* PASV command (command not supported) or fails to recognize the command, it will * return ERROR.** This routine must be called \f2before\fP the data-transfer command is sent;* otherwise, the server's connect may fail.** This routine is called after ftpHookup() and ftpLogin() to establish a* connection with a remote FTP server a low level. (For a* higher-level interaction with a remote FTP server, see ftpXfer().)** This function is preferred over ftpDataConnInit() because * the remote system must preserve old port connection pairs even if the target * system suffers from a reboot (2MSL). Using PASV we encourage the host's * selection of a fresh port.** RETURNS: The file descriptor of the data socket created, or ERROR.** SEE ALSO: ftpHookup(), ftpLogin(), ftpCommandEnhanced(), ftpXfer(), ftpConnInit()**/int ftpDataConnInitPassiveMode ( int ctrlSock /* fd of associated control socket */ ) { FAST int dataSock; int result; int len; int portMsb; int portLsb; int hostDataPort; SOCKADDR_IN ctrlAddr; SOCKADDR_IN dataAddr; /* If configured to disable PASV mode, then just return ERROR */ if (ftplPasvModeDisable) return (ERROR); /* find out our inet address */ len = sizeof (ctrlAddr); if (getsockname (ctrlSock, (struct sockaddr *)&ctrlAddr, &len) < 0) { FTPLDEBUG ("ftpDataConnInitPassiveMode: getsockname() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); return (ERROR); } result = ftpCommandEnhanced (ctrlSock, "PASV", 0,0,0,0,0,0, /* XXX - These arguments not needed */ pasvReplyString, PASV_REPLY_STRING_LENGTH-1); if (result == FTP_PASSIVE_REPLY) /* The remote FTP server supports PASSIVE mode */ { /* Parse the last line of the reply */ ftpPasvReplyParse (pasvReplyString, 0, 0, 0, 0, &portMsb, &portLsb); /* Convert port number */ hostDataPort = portMsb * 256 + portLsb; /* make our data socket */ dataSock = socket (AF_INET, SOCK_STREAM, 0); if (dataSock < 0) { FTPLDEBUG ("ftpDataConnInitPassiveMode: error - failure to get socket. errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, errno,1,2,3,4,5); return (ERROR); } bzero ((char *) &dataAddr, sizeof (SOCKADDR)); /* Use the port given to us in the reply of our PASV command */ dataAddr.sin_port = htons (hostDataPort); dataAddr.sin_family = AF_INET; len = sizeof (SOCKADDR_IN); if (getpeername (ctrlSock, (struct sockaddr *)&ctrlAddr, &len) < 0) { FTPLDEBUG ("ftpDataConnInitPassiveMode: getpeername() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); close (dataSock); return (ERROR); } dataAddr.sin_addr.s_addr = ctrlAddr.sin_addr.s_addr; /* connect to the host */ if (connect (dataSock, (struct sockaddr *)&dataAddr, sizeof (dataAddr)) < 0) { FTPLDEBUG ("ftpDataConnInitPassiveMode: failure to connect. sock:%d sockMsb:%d sockLsb:%d errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, hostDataPort, portMsb, portLsb, errno, 5, 6); close (dataSock); return (ERROR); } else { FTPLDEBUG ("ftpDataConnInitPassiveMode: passive ftp connect established to host:%#x port:%d sock:%d\n", \ FTPL_DEBUG_ERRORS, dataAddr.sin_addr.s_addr, hostDataPort, dataSock,4,5,6); return (dataSock); } } else /* We have failed PASV mode */ { FTPLDEBUG ("ftpDataConnInitPassiveMode: host failed to respond correctly to PASV command. errno:0x%08x\n", \ FTPL_DEBUG_ERRORS, errno,1,2,3,4,5); return (ERROR); } }/********************************************************************************* ftpDataConnInit - initialize an FTP data connection using PORT mode** This routine sets up the client side of a data connection for the* specified control connection using the PORT command. * It creates the data port, informs the* remote FTP server of the data port address, and listens* on that data port. The server will then connect to this data port* in response to a subsequent data-transfer command sent on the* control connection (see the manual entry for ftpCommand()).** This routine must be called \f2before\fP the data-transfer command is sent;* otherwise, the server's connect may fail.** This routine is called after ftpHookup() and ftpLogin() to establish a* connection with a remote FTP server at the lowest level. (For a* higher-level interaction with a remote FTP server, see ftpXfer().)** Please note that ftpDataConnInitPassiveMode() is recommended instead* of ftpDataConnInit().** RETURNS: The file descriptor of the data socket created, or ERROR.** SEE ALSO: ftpDataConnInitPassiveMode(), ftpHookup(), ftpLogin(), * ftpCommand(), ftpXfer()*/int ftpDataConnInit ( int ctrlSock /* fd of associated control socket */ ) { FAST int dataSock; int result; int len; int optval; SOCKADDR_IN ctrlAddr; SOCKADDR_IN dataAddr; /* find out our inet address */ len = sizeof (ctrlAddr); if (getsockname (ctrlSock, (struct sockaddr *)&ctrlAddr, &len) < 0) { FTPLDEBUG ("ftpDataConnInit: getsockname() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); return (ERROR); } /* first try - try to send port */ dataSock = socket (AF_INET, SOCK_STREAM, 0); if (dataSock < 0) { FTPLDEBUG ("ftpDataConnInit: socket() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); return (ERROR); } dataAddr = ctrlAddr; /* set our inet address */ dataAddr.sin_port = htons (0); /* let system pick port num */ if (bind (dataSock, (struct sockaddr *)&dataAddr, sizeof (dataAddr)) < 0) { FTPLDEBUG ("ftpDataConnInit: bind() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); close (dataSock); return (ERROR); } if (listen (dataSock, 1) < 0) { FTPLDEBUG ("ftpDataConnInit: listen() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); close (dataSock); return (ERROR); } /* try to send socket address to other side */ len = sizeof (dataAddr); if (getsockname (dataSock, (struct sockaddr *)&dataAddr, &len) < 0) { FTPLDEBUG ("ftpDataConnInit: getsockname() failure. errno:0x%08x", \ FTPL_DEBUG_ERRORS,errno,1,2,3,4,5); close (dataSock); return (ERROR); }#define UCA(n) (((int)(((char *)&dataAddr.sin_addr)[n])) & 0xff)#define UCP(n) (((int)(((char *)&dataAddr.sin_port)[n])) & 0xff) result = ftpCommand (ctrlSock, "PORT %d,%d,%d,%d,%d,%d", UCA(0), UCA(1), UCA(2), UCA(3), UCP(0), UCP(1)); if (result != FTP_ERROR) { if (result == FTP_PRELIM) { FTPLDEBUG ("ftpDataConnInit:warning got FTP_PRELIM. ", \ FTPL_DEBUG_ERRORS,0,1,2,3,4,5); } if (result != FTP_COMPLETE && result != FTP_PRELIM) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -